質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

879閲覧

構造体を返してみてうまくいかない

txty

総合スコア303

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2024/11/26 09:48

編集2024/12/02 12:40

実現したいこと

行列の構造体を返したいです。

発生している問題・分からないこと

struct でメンバー作った後、疑似コードになりますが初期化で、ここはCopilotですが(0,0 行列の構造体, 10,10,行列の構造体 20,100,行列の構造体 30,200,行列の構造体)としたとき、return行列の構造体としたとき、行列にははじめの値しか入っていないけど考えられない数値1440とかが出力されます。行列のかけ算にglmultimatrixだったかとその分類を使いました。

該当のソースコード

/*行列を取得するコード*/ struct DataFrame { float mframe[16]; }; struct Result { float Result[16]; }; /*c++ってほどでもないけどclassでした。お詫びして訂正いたします。*/ DataFrame mframe[1024]; /* 関数 */ Result gettime(double t) { DataFrame interpolated; for (int i = 0; i < 16; ++i) { interpolated.mframe[i] = /*数式を省略*/ } /*glMultMatrixf 行列の掛け算などの類の処理を数行⋆/ glMultMatrixf(interpolated.mframe); glGetFloatv(GL_MODELVIEW_MATRIX, mResult[0].Result); // 結果をresultMatrixに取得 一部省略。 /*行列の計算はあってる*/ for (int i = 0; i < 16; ++i) { printf("%f ", interpolated.mframe[i]); } return mResult[0]; }/*関数の終わり*/ void draw() { struct Result d = gettime(35); /*ここの行列の値がへん*/ for (int i = 0; i < 16; ++i) { printf("%f ", d.Result[i]); }

うちながらstruct等をcopilotでこまめに表示しました。

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

return 行列の構造体
として返り値で一番始めの変数を調べましたところ、ひとまず大きな値が出力されます。ただ同じブロック内なら計算できてるようです。

補足 

IdentityMatrixの間違いでした。(試してみたコードで最後に使う予定だったので最後がくるまでどうなるかわからないですが)、質問には関係ないことで補足します。glmultiMatrixは、行列はとけるけど、頂点Vertex[4]?のことは分かりかね、投げるとえらーになることをcopilotがいってたようでした(4x4を自前で用意してということでした。)間違えてしまいすいません。

本のコードの部分は載せられないため、載せませんでした。載せてほしいといわれてもちょっと無理です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

juner

2024/11/26 10:01

> 疑似コード どこに疑似コードがあるのでしょうか?
txty

2024/11/26 10:03

コメントありがとうございます。copilotの部分になると思ったんですが擬似コードとは呼ばないのでしょうか
fana

2024/11/26 10:12 編集

「行列の構造体」なるものの定義や,「返す」とか「初期化」の具体的な実装を提示できない状況にあるのであれば, 本件(その見せられない実装の動作結果が異常となる理由等)の話をこういう場所で質問すること自体が難しい(というか無理なんじゃないかな)と思います. 仮に,何らかの「疑似コード」を示すとしても,そこに「本物のコードに存在する問題点」が含まれているとは限らないし…… しかし,「問題が再現する最小限のコード例」として,「本物のコードと意味的に同じ形の処理をする別のコード」というのをあなたが用意することができるのであれば,それを用いて質問すれば良いのではないか? という気がします.
txty

2024/11/26 10:26 編集

コメントありがとうございます。わたしもむずかしいとおもったんですけど、一応出しとくぶんにはただかと思いその経緯でだしてました。いつだったかのスレッドも差し伸べられた手だったことが分かりました。同じ意図を示したコードをだすのは、ちょっときついですね。数学がまずわからないですし用意できないです。
dodox86

2024/11/26 10:59

> 数学がまずわからないですし用意できないです。 本質的には数学は関係無くて、C言語で求める行列の構造を表した構造体やその配列を呼び出された関数がreturnで返すか、ポインターを介して呼び出し元へデータを返せるか、の問題ではないでしょうか。データ構造をちゃんと把握できていればそんなに難しいことのようには思えませんが、、、 > 一応出しとくぶんにはただかと思いその経緯でだしてました。 あんまり「ぶん投げ」感があると、回答者の方も気がそげちゃいますよ。閲覧すら避けられるでしょう。
txty

2024/11/26 11:24

コメントありがとうございます。structを避けてきたんでむずかしいのかもしれません。勉強してみます。 閲覧すらさけられるでしょう。今後しだいですかね、
TakaiY

2024/11/26 11:30

> 疑似コード > copilotの部分になると思ったんですが擬似コードとは呼ばない 呼びません 一般に、疑似コードというのは、実際に使う目的で作ったコードではなく、実現しようとしているアルゴリズムなどを説明するために作ったコードのことを指します。説明部分を自然言語で書いたりしてあることが多いですね。 Copilot等のヘルパで作ったコードであればそう書くか、未完成のコードなどと書くのがいいのではないかと思います。
TakaiY

2024/11/26 11:31

質問については、関数ローカルのデータだったり、単にポインタだけ作ったものだったりの、実体の無いものであることが原因と思いますが、コードが無ければ何とも言えませんね。
txty

2024/11/26 11:56

訂正してくださりありがとうございます。とても勉強になります。コードがだせなくてすいません。
melian

2024/11/27 13:32

gettime() 関数内の return mResult[0]; ですが、この mResult という変数はどこで定義しているのでしょう?
txty

2024/11/27 13:39

コメントありがとうございます。/*c++ってほどでもないけどclassでした。お詫びして訂正いたします。*/ DataFrame mframe[1024];の下になります。
jimbe

2024/11/27 13:44 編集

(melianさんと被ったので消しました^^;)
txty

2024/11/27 13:47

使用場所を訂正しました。ソースコードに追記しました。
jimbe

2024/11/27 13:51

gettime 関数内で、 interpolated.mframe の内容は表示確認されているようですが mResult[0] の内容は表示確認されていないんでしょうか。
txty

2024/11/27 14:40

あたりです。mResult[0]でおかしな値2357が出ました。ここをなおせば、正解かもしれませんが、どうすればいいのか、ちょっとわからないです。すいません、ちょっと今日は切り上げて寝ます。
jimbe

2024/11/27 15:30

>どうすればいいのか コードを逆に辿って mResult[0] に値を設定している所を見つけてその計算があっているかを見つけるしかありません。 もしかするとここからは数学が関係するのかもしれませんが、それも該当コードが提示されなければこちらには全く分かりませんので、 txty さんが地道に探すしかないかもしれません。
guest

回答1

0

ベストアンサー

※ 問題がハッキリしないのでまだ回答になっていません。

例えば以下のような感じのコードでは、一見正常に動作しているように見えてもバグが隠れていて、それが表面化すると d に変な値が現れます。(このような小さくすぐ終わるようなプログラムではなかなか表面化しずらいですが。)
お手元のコードの、計算する関数やその結果を受け取る個所はこのようにやってはいないでしょうか。

c

1#include <stdio.h> 2#include <string.h> 3 4struct Data { 5 int v[10][10]; 6}; 7 8void print(char *s, struct Data *z) { 9 printf("-- %s --------\n", s); 10 for(int i=0; i<10; i++) { 11 for(int j=0; j<10; j++) { 12 printf(&",%d"[j==0], z->v[i][j]); 13 } 14 printf("\n"); 15 } 16} 17 18struct Data *calc(struct Data *a, struct Data *b) { 19 struct Data c; 20 memset(&c, 0, sizeof(c)); 21 for(int i=0; i<10; i++) c.v[i][i] = i+1; /*数学的な計算は関係無いのでテキトウな(確認し易い)値を設定しておく*/ 22 print("c", &c); 23 return &c; 24} 25 26int main(void){ 27 struct Data a, b; 28 memset(&a, 0, sizeof(a)); 29 print("a", &a); 30 memset(&b, 0, sizeof(b)); 31 print("b", &b); 32 33 struct Data *d = calc(&a, &b); 34 print("d", d); 35}

(質問へのコメントより)

どうすればいいのか

コードを逆に辿って mResult[0] に値を設定している所を見つけてその計算があっているかを見つけるしかありません。
もしかするとここからは数学が関係するのかもしれませんが、それも該当コードが提示されなければこちらには全く分かりませんので、 txty さんが地道に探すしかないかもしれません。

投稿2024/11/27 05:17

編集2024/11/28 10:32
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

txty

2024/11/27 09:20

回答ありがとうございます。 >お手元のコードの、計算する関数やその結果を受け取る個所はこのようにやってはいないでしょうか。 そのコードのどこがおかしいか教えてもらっていいでしょうか。 何回も、かき直したくなると思うので上のコメントに少しコードの断片をかいてもよろしいでしょうか。copilotを使っています。
jimbe

2024/11/27 11:59

>そのコードのどこがおかしいか 構造体に限りませんが、関数内で宣言した変数の領域は関数内でのみ有効であり関数を出たら消滅すると考えなければなりません。 19 行目で生成した c は 20 行目から 23 行目まででのみ有効であり、 return で返したアドレスを 33 行目で d として受け取った時点で有効範囲を超えているので、 d の指す (元 c だった) メモリの中身は保証されません。 >上のコメントに少しコードの断片をかいてもよろしいでしょうか 「上のコメント」というのは「質問へのコメント」のことでしょうか。 質問へのコメントは回答しようとする側が質問者へ何か伝えたいことがある場合("〇〇はどうなっていますか?"等)に書く場所です。ですので、質問に関する情報は質問を編集して修正・追記するようにしてください。 その際は、 teratail は質問者の問題が解決すれば良いだけという場所では無く、Q&A の形で同じ問題を抱えている人が後から見て解決できるように情報を蓄えておくことも目的とされていることもご留意ください。 質問するときのヒント https://teratail.com/help/question-tips >copilotを使っています。 ツールとして何を用いられていても構いませんが、 AI が生成したからと言って何の間違いも無いとは言い切れませんし、まして AI に責任を問うことは出来ませんのでどのような件であれ最終的にはその利用者が責任を取らざるを得ないと考えます。従って、 AI が生成したから自分には分からないというのは言い訳にもなりませんので、きちんと内容を理解した上でご提示をお願いします。
txty

2024/11/27 13:28

ソースコードの断片を追加しました。ご確認いただけると幸いです。後乗せてもらったソースコードは、同じ現象でおかしいのか、補足してもらえますか。 >19 行目で生成した c は 20 行目から 23 行目まででのみ有効であり、 return で返したアドレスを 33 行>目で d として受け取った時点で有効範囲を超えているので、 d の指す (元 c だった) メモリの中身は保証>されません 少し理解が進まなくて。
jimbe

2024/11/27 14:18

struct Result { float Result[16]; }; struct Result mResult[1024]; struct Result gettime(double t) { : return mResult[0]; } struct Result d = gettime(35); だとすれば、現状の回答のコードとは違います。 回答のはアドレスを返す書き方ですが、こちらは mResult 配列の要素 0 を返す書き方ですので、mResult[0] の内容が d にコピーされます。つまり構造体の中身はちゃんと呼び出し側に帰っているはずです。 なら、呼び出し側で d の中身を確認して想定外の値が入っているとすれば、そも gettime 内ですでに mResult[0] にそのような値が入っているのかもしれません。 gettime 関数内で interpolated.mframe の内容は表示確認されているようですが mResult[0] はされていないようです。 gettime 関数内で return の直前で mResult[0] の内容を表示してみては如何でしょうか。
txty

2024/11/28 07:44 編集

回答ありがとうございます。 struct の形になっていませんが float identityMatrix[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };として、 glPushMatrix();        //copilotです。よく理解できてないです。 glLoadMatrixf(identityMatrix); // ここで mframe[0] をロード identityMatrixが、interpolated.mframeになっていました。  .. 試したところ問題が解決しました! 前を探した結果なので、ベストアンサーに選びたいので、回答のコメントを回答に書いてもらってよろしいでしょうか。
jimbe

2024/11/28 09:47

前を探したというのは、質問へのコメントに最後に書いた「コードを逆に辿って…」のことでしょうか。
txty

2024/11/28 09:58

はい、そうです。
jimbe

2024/11/28 10:10

お疲れさまでした。 あっちもこっちも分からない状態だとなかなか要領よくはいかないと思いますが、諦めなければいつか分かると思いますので頑張ってください。
txty

2024/11/28 10:29 編集

ありがとうございます。勉強つづけてみます。ベストアンサーに選びたいのですが、どうすれば宜しいでしょうか。最後までお手を煩わせてしまい申し訳ございませんでした。
jimbe

2024/11/28 10:31

質問をしたことがないのでハッキリ言えないのですが、回答の何処かに「ベストアンサー」ボタンとか無いでしょうか(^^;
txty

2024/11/28 10:34

ありますが、コードをたどってと回答コメントにあるので、上の回答をベストアンサーに選んでよろしいでしょうか。
txty

2024/11/28 10:39

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。ありがとうございました。
jimbe

2024/11/28 10:47 編集

先に書いていた回答を消してしまうと「回答へのコメント」でのやり取りが意味不明になってしまうので、区切りとして横線を入れて「質問へのコメント」からコピペしたのですが、ちょっと分かりにくかったですかね>< 再度、お疲れさまてした。
txty

2024/11/28 13:06

分かりやすいです。ノシ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問