- 締切済み
ポインタと二次元配列
ポインタを習ったんですが、二次元配列を指定する場合はどのようにすればいいのでしょうか? また、別関数でそのポインタを呼びたいのですが。 (例) main関数 char retsu[2][2] = {{2,4},{6,8}}; char *ptr; next関数 上記でいくと「main関数内のchar retsuの二次元配列を*ptrで指定」、「next関数でmain関数で指定した*ptr(retsu[2][2])を参照したい」 という事をしたいのですが、教えて下さい。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- kumonomoto
- ベストアンサー率41% (12/29)
ちょっと長い説明になりますがご容赦下さい。 ■「1 番目の引数を 'int (*)[40]' から 'int *' に変換できません。」 void next1( int (*ptr)[40] ){} void next2( int *ptr ){} main() { int retsu[2][40] = { 0 }; int (*ptr)[40] = retsu; next1( ptr ); next2( ptr ); //こっち側でエラー } next1ではなく、next2の書き方をしてエラーを出してはいませんか? int (*ptr)[40] と int *ptr は同じポインタですが、そのままでは代入は出来ません。 とは言ってもポインタには変わりないのでキャストしてしまえばいいだけですが。 void next1( int (*ptr)[10] ) { for( int x = 0 ; x < 5 ; x++ ){ for( int y = 0 ; y < 10 ; y++ ) printf( "% 3d", ptr[x][y] ); printf( "\n" ); } } void next2( int (*ptr)[5][5] ) { for( int x = 0 ; x < 2 ; x++ ){ printf( "x = %dですよ。\n", x ); for( int y = 0 ; y < 5 ; y++ ){ for( int z = 0 ; z < 5 ; z++ ) printf( "% 3d", ptr[x][y][z] ); printf( "\n" ); } printf( "\n" ); } } main() { int retsu[50]; int* ptr = retsu; for( int i = 0 ; i < 50 ; i++ ) retsu[i] = i + 1; next1( (int (*)[10])ptr ); printf( "\n\n" ); next2( (int (*)[5][5])ptr ); } 配列は2次元でも3次元でも領域の確保の仕方は1列です。 ですから[50]も[5][10]も[2][5][5]も皆一緒ですので、慣れてしまえばこういう風にも使えます。 int[000]-変数[数値]という記述は、変数のアドレスに数値分だけ進めた場所のアドレスに 入っている値を取り出すことです。 int i[5][10]; という変数があったとすると、 i[0][0] = *i i[0][1] = *(i + 1) i[0][2] = *(i + 2) i[1][7] = *(i + ((1 * 10) + 7)) = *(i + 17) i から17個分先のアドレスに入っている値を取り出すという意味になります。 int i[3][20]; という風に配列の要素数が変われば、 i[1][7] = *(i + ((1 * 20) + 7)) = *(i + 27) = 27個分先のアドレスの値 のようになります。
- kumonomoto
- ベストアンサー率41% (12/29)
charからintに変えてますが、こういう書き方が出来ます。 void next( int (*ptr)[2] ) { printf( "ptr[0][0]=%d\n", ptr[0][0] ); printf( "ptr[0][1]=%d\n", ptr[0][1] ); printf( "ptr[1][0]=%d\n", ptr[1][0] ); printf( "ptr[1][1]=%d\n", ptr[1][1] ); } main() { int retsu[2][2] = { { 2, 4 },{ 6, 8 } }; int (*ptr)[2] = retsu; next( ptr ); } int (*ptr)[2] ↑何これ? と思うでしょうが、わかりやすいように書くと、 int[2]* ptr となります。 つまりはint2個の配列へのポインタです。 が、こう書くとエラーになってしまいますので注意して下さい。
補足
お返事遅くなりました。 上のを踏まえ自ソースに組み込んだのですが、「1 番目の引数を 'int (*)[40]' から 'int *' に変換できません。」と出てしまいました。 エラー行は別関数に渡す所でした。 これはどういう意味なのでしょうか。
- SnowShower
- ベストアンサー率40% (140/348)
渡す配列の要素数がわかっている場合の一例 #define A_MAX 2 #define B_MAX 3 void sample( char *a_ptr, int a_x, int a_y) { char i; i = *(a_ptr + (a_x * B_MAX) + a_y); printf(" %d,%d i = %d\n", a_x, a_y, i); } int main(void) { char retsu[A_MAX][B_MAX] = {{2,4,1},{6,8,3}}; char *ptr; ptr = &retsu[0][0]; sample( ptr, 0, 0 ); sample( ptr, 0, 1 ); sample( ptr, 0, 2 ); sample( ptr, 1, 0 ); sample( ptr, 1, 1 ); sample( ptr, 1, 2 ); return 0; }
補足
なるほど。 要素数が分かっている場合は直で数字を渡してやればいいんですね。 途中の i = *(a_ptr + (a_x * B_MAX) + a_y); っと難しい式がありますが、どういう事なのでしょう。
お礼
なるほど。 キャストという手があったんですね。 やってみます。ありがとうございました。