• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:2次元配列からダブルポインタへの合わせ方)

2次元配列からダブルポインタへの合わせ方

このQ&Aのポイント
  • 固定要素数の行列の処理ですが、subでセグメンテーション違反が発生しています。
  • 呼び出し側で行列の先頭のアドレスを明示しているつもりですが、どこが間違っているのでしょうか。
  • typedefとsubのIFを合わせなければならず、合わせ方が分かりません。

質問者が選んだベストアンサー

  • ベストアンサー
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.5

別物なのでそのままでは合わせようがないです。どうしてもというなら const double *m[] = {mat[0], mat[1], mat[2]}; としたものを sub(m); で渡すしかないんじゃないか。

aneja
質問者

お礼

ご回答ありがとうございます。 Illegal initialization というコンパイルエラー(Borland)が出ましたが、typedefしたものをラップすればよいという理解でよいですか。動くようにがんばってみます。

すると、全ての回答が全文表示されます。

その他の回答 (13)

noname#137556
noname#137556
回答No.14

ANo.8 の回答をしたものです。 「ANo.5 が正解」と書きましたが,場合によっては正解ではないかもしれません。 コンパイル時・実行時にエラーにならなくても,意味的に間違っている可能性はあります。 例えば,要素を格納する順番までは,引数の型だけでは分からないので。 列方向優先で格納することも比較的よくあります。 とにかく, sub 関数がどういうデータを要求しているか,よく確認して下さい。 そして,それに合ったデータを用意してあげてください。 # 全要素のコピーが必要になるかも

aneja
質問者

お礼

何度もご回答、ありがとうございます。 既存の(自分が作ったものではない)関数を使う時は、おっしゃる通りの確認が必要ですね。間違えないように気をつけます。

すると、全ての回答が全文表示されます。
  • knb-nkm
  • ベストアンサー率66% (4/6)
回答No.13

A No.6の者ですが、ちょっと間違っていたので補足です。 double (*mat)[3]; mat = (double (*)[3])mat_; が正しいですね。Matrixにキャストしても意味が無い(--; それから、呼び出し側もとりあえず、 sub( (const double **)mat ); で動きます。(gcc -Wall では) キャストで逃げるのは邪道な気はしますが、事情があれば仕方ないですね。

aneja
質問者

お礼

何度もご回答、ありがとうございます。 こういう方法があるのですね。勉強になりました。

すると、全ての回答が全文表示されます。
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.12

> 以下のワーニングがでています(Borland)。 質問そのものへの回答は既に他の方が挙げられていますのでほぼ解決していると思いますが、この警告が「何を言っているか」は理解していますか?

aneja
質問者

お礼

ご回答、ありがとうございます。 警告の内容は、「ポインタに変換した型が一致していない疑いあり」という感じでしょうか。sub内ではポインタのポインタとして引数を扱わないといけないのに、呼び出しで指定したポインタは、(単なる最初の要素へのポインタということで)シングルポインタになっているから合っていない、と言われているのかと理解しました。

すると、全ての回答が全文表示されます。
  • trapezium
  • ベストアンサー率62% (276/442)
回答No.11

エラー? と思ったので gcc で確認してみた Matrix mat = {{ 0., 1., 2. }, { 3., 4., 5. }, { 6., 7., 8. }}; double *m[] = {mat[0], mat[1], mat[2]}; として sub(m); エラーなしで一応動作するけど? それから、私も既存ライブラリにインタフェース合すということは良くあるので、今回もそうだろうと思いましたが、そういう事は最初に書いておくべきでしたね。

aneja
質問者

お礼

ご回答、ありがとうございます。 そのままコピペさせていただきましたが、なぜか、Borlandではエラーが出ます…。 質問の仕方は、今後気をつけます。

すると、全ての回答が全文表示されます。
noname#137556
noname#137556
回答No.10

既存のコードとかライブラリを使うとかで,インターフェイスを変更できないこともありますよね。 その場合は, 要求に合ったデータを呼び出し側で作るしかないので,ANo.5 が正解だと思う。

aneja
質問者

お礼

ご回答ありがとうございます。 動くようになんとかがんばってみます。

すると、全ての回答が全文表示されます。
回答No.9

typedef は、新たな型宣言と同じだから、Matrixを渡すのに、double**は、間違い。 そもそも、**の解釈が正しくない。 Answer8の方が一番正解。 出題者の、意図を聞いてみたい。

aneja
質問者

お礼

ご回答ありがとうございます。 確かに、Matrixからdouble**へはそのままでは渡せないですね。大人の事情(No.7の方へのお礼に記載)のために悩んでいたところです。

すると、全ての回答が全文表示されます。
  • yama5140
  • ベストアンサー率54% (136/250)
回答No.8

>呼び出し側では「行列の先頭のアドレス」を明示したつもりだったのですが、どこが間違っているのでしょうか。  「間違っている」というより、せっかく typedef したのだから、const double** はないような。  typedef const double Matrix[3][3];  void sub( Matrix mat ); // プロトタイプ   ・   ・    sub( mat ); // 関数呼び出し   ・   ・  void sub( Matrix mat )  // 関数本体   ・ でエラーは出ませんよ。

aneja
質問者

お礼

ご回答ありがとうございます。 おっしゃる通りで、ご回答の通りにしたいのですが、大人の事情(No.7の方へのお礼に記載 )でそういうわけにもいかなくなったのです。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.7

main では sub((void *)mat); のように void * に変換して逃げ, sub で void sub( const double** mat_ ) { Matrix *mat = (const void *)mat_; /* 以下略 */ とするかなぁ.... そもそも「subのIFは変更できない」という条件がなぜ付いているのか理解できないのだが.

aneja
質問者

お礼

ご回答ありがとうございます。 voidポインタってこういう時に威力を発揮するのですね! 今回の問題は、typedefの方は相手の承認を得てしまっているのでもう変更できない、subの方は既存の実績ある関数で、これをそのまま使おうという方針になったことが発端なのです。

すると、全ての回答が全文表示されます。
  • knb-nkm
  • ベストアンサー率66% (4/6)
回答No.6

double ** は、double * へのポインタなので、 double * の指す先に何が入っているのか、コンパイラには 判断がつきません。 今回の場合は、double A[3][3]; と、サイズが分かっているので、 以下の様に、配列サイズを教えてあげる必要があります。 void sub( const double** mat_) { int i, j; double (*mat)[3]; mat = (Matrix)mat_; printf("---- &mat = %p\n", &mat ); ... みたいな感じかな。

aneja
質問者

お礼

ご回答ありがとうございます。 最初の[]以外の配列サイズは教えてあげる必要があることは理解しました。 mat = (Matrix)mat_; のところで、Incompatible type conversion とエラーが出た(Borland)のですが、なんとか動くようにがんばってみます。

すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2127/6290)
回答No.4

>(*mat)[3] >という具合に、sub関数に渡す引数を 念のため。 こういう風に書く(必要があるかもしれない)のは、 関数プロトタイプ宣言や 関数の実体定義における引数の記載部分です。

aneja
質問者

お礼

2度もご回答ありがとうございます。 どうしてもリテラルが入ってしまうんですね…。

すると、全ての回答が全文表示されます。

関連するQ&A