• ベストアンサー

配列とポインタについて

以下のような matrixの二次元配列の引数があるのですが、これを keisan2に渡す時にどのように記述すれば良いのでしょうか? ???部分が知りたいです。 また、char **matrixと matrix[][3]は違うものですか? 覚えるコツも知りたいです。 int keisan(int data, char matrix[][3]) { // 省略 return keisan2(dat, ???); } int keisan2(int data, char matrix[][3]) { // 省略 return 0; }

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

  • ベストアンサー
回答No.7

参考HPでも載せときますね http://www.geocities.co.jp/SiliconValley-Bay/7437/c/c4.htm http://sometime.minidns.net/~ccgi/pointer_array.html ポインタ配列とポインタのポインタを同じだと言い張る人がいて驚いた。

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

その他の回答 (9)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.10

char matrix[][3] における matrix の型は char[][3]>#9. ポインタに変換されたあとでは char (*)[3].

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

突っ込みたくて、アカウントまでとってしまいました^^;; >また、char **matrixと matrix[][3]は違うものですか? >覚えるコツも知りたいです。 何人かのかたも回答していますが別のものです。 「型」を意識すると理解できると思います。 char **matrix はあくまで 「char **」という型ですが matrix[][3] はたぶん、「char」という型です。 (char は僕の補完です。) 両者を同じに考えていると将来、メモリ周りで悩むことになるかもしれません。 #include <stdio.h> int main(int argc, char *argv[]) { char a[][4] = {"ABC", "DEF", "GHI" }; char *b[4] = {"abc", "def", "ghi" }; a[0][0] = 'R'; b[0][0] = 'r'; // ← NG printf("%s\n", a[0]); printf("%s\n", b[0]); return 0; }

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

#6 の 1行目を詳しく書くと, #5 の matrixsub において各引数はそれぞれ char **matrix1, char matrix2[][3], char *matrix3[3] と宣言されています. このうち matrix1 の型は直ちに char ** であることがわかります. 問題は matrix2, matrix3 ですが, これはそれぞれ「char [3] の配列」及び「char * の大きさ 3 の配列」と宣言されています. しかし, C/C++ の規格では「引数を配列と宣言した場合, 自動的にポインタであると解釈する」という規定があります. なので, コンパイラが理解する本当の型はそれぞれ「char [3] へのポインタ」, 「char * へのポインタ」です. 従って, 実際にはそれぞれ char (*matrix2)[3], char **matrix3 であるとみなされます (matrix2 でかっこが付いているのは優先順位の関係による). つまり, matrix1 と matrix はどちらも同じ型 char ** であり, 同じ扱いを受けるのが自然です.

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

matrixsub において matrix1 と matrix3 は同じ型を持つので, その要素にアクセスするコードも全く同じになるのが自然なんですけど>#5. #3 はそんなことは言ってなくて, 例えば void foo() { int matrix1[4][3]; int *matrix2[4]; int **matrix3; int x, y; /* matrix2, matrix3 は適切にメモリが割り当てられているとする */ printf("%d %d %d\n", matrix1[x][y], matrix2[x][y], matrix3[x][y]); /* 以下略 */ } の printf のところでアクセスするコードが違うよね, って話でしょう. この場合 matrix1, matrix2, matrix3 はすべて異なる型であり, 実際に違うコードが出るはずです. 「違う」ことがあまりにも明らかなので確かめる気はありません.

すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.5

横から失礼します。 私も、 char **matrix; char *matrix[3]; は同じだと思うんですよ、なので代わりに検証コードを書いてみました。 cygwinのgccを使っています。 void matrixsub( char **matrix1, char matrix2[][3], char *matrix3[3]); int main(void) { char matrixA[3][3]; char *matrixB[3]; char matrixB0[3]; char matrixB1[3]; char matrixB2[3]; int i,j; matrixB[0] = matrixB0; matrixB[1] = matrixB1; matrixB[2] = matrixB2; for( i=0; i<3 ; i++ ) { for( j=0; j<3 ; j++ ) { matrixA[i][j] = i*10+j; matrixB[i][j] = 100+i*10+j; } } matrixsub( matrixB, matrixA, matrixB ); } void matrixsub( char **matrix1, char matrix2[][3], char *matrix3[3]) { int i,j; for( i=0; i<3 ; i++ ) { for( j=0; j<3 ; j++ ) { printf( "1:%02d 2:%02d 3:%02d ", matrix1[i][j], matrix2[i][j], matrix3[i][j] ); printf( "\n" ); } } } で、オプティマイズ無しコンパイル時のアセンブルコードのprintfの一部分を載せます。 movl -4(%ebp), %eax # i, i leal 0(,%eax,4), %ecx #, tmp60 movl 16(%ebp), %edx # matrix3, matrix3 movl -8(%ebp), %eax # j, j addl (%ecx,%edx), %eax #* matrix3, tmp62 movsbl (%eax),%eax #, tmp64 movl %eax, 12(%esp) # tmp64, movl -4(%ebp), %edx # i, i movl %edx, %eax # i, i addl %eax, %eax # i addl %edx, %eax # i, i addl -8(%ebp), %eax # j, tmp67 addl 12(%ebp), %eax # matrix2, tmp68 movsbl (%eax),%eax #, tmp69 movl %eax, 8(%esp) # tmp69, movl -4(%ebp), %eax # i, i leal 0(,%eax,4), %ecx #, tmp72 movl 8(%ebp), %edx # matrix1, matrix1 movl -8(%ebp), %eax # j, j addl (%ecx,%edx), %eax #* matrix1, tmp74 movsbl (%eax),%eax #, tmp76 movl %eax, 4(%esp) # tmp76, アセンブルコードを見ると分ると思いますが、matrix1と3は同じに扱われます。matrix2はやはり違う扱いを受けています。 思った通りと言うか、なるほどやっぱりな結果でした。

kourei
質問者

補足

非常に混乱しそうですが、アセンブルの結果で同じだったからといって 同じものだといえるのでしょうか? ポインタのポインタは、単なるポインタをセットするのみで ポインタ配列にならないと思いますが・・・?

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

>#3さん >どれも「値を取り出す時に、同じ書き方が可能」ですが「実際に値を取り出す方法」は違っています。 どうもここのところがしっくりこないので、 サンプルコードか何かで動きを体感できるように していただけませんでしょうか?

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

>また、char **matrixと matrix[][3]は違うものですか? 違う物です。メモリ上のデータの配置を考えてみて下さい。 char **matrix; は 「どこかにcharへのポインタがあって、matrixは、その謎のポインタのアドレスを指してるポインタ変数」 です。 char matrix[][3]; は 「要素数が3の1次元配列(つまりcharが3個並んだ配列)が、(何個か不明だが)たくさん並んだ配列」 です。 char *matrix[3]; は 「charへのポインタが3つ並んだ(つまり、どこかを指すアドレスだけが、3つ並んでる)配列」 です。 どれも「値を取り出す時に、同じ書き方が可能」ですが「実際に値を取り出す方法」は違っています。

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

・T ** は「T型へのポインタへのポインタ」 ・T [][3] は「T型の大きさ 3 の配列の (大きさが未定の) 配列」もしくは (関数の引数宣言では配列が自動的にポインタに変換されるので) 「T型の大きさ 3 の配列へのポインタ」 なので, この 2つは別物です. しいていうと「int へのポインタ」と「double へのポインタ」くらい違うと思っていい. 余談ですが, 使い勝手を考えると 2次元配列を T matrix[5][5]; のように取るのはやめた方がいいと思う. 可能なら T **matrix; ととった上で動的に取る方があとで便利.

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

???部分は return keisan2(dat, matrix); です。 >また、char **matrixと matrix[][3]は違うものですか? コンパイル時にプロトタイプ宣言と変数定義が違った場合は エラーになります。変数定義で char *matrix[3]; と書いた場合は「**matrix」でも通りますが、ミスが見つけにくく なるので書かない方が無難だと思います。

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

関連するQ&A