ページ 11

ポインタと配列について(初心者です)2

Posted: 2009年6月16日(火) 14:25
by たくや
昨日こちらでお世話になったものです。
初心者の僕にも分かるよう親切に解説してくださり助かりました。みなさまに感謝しております。
昨日に引き続き質問させていただきます。

昨日の問題の続編として以下のような課題が出されました。


int 型の二次元配列 a[3][4] を定義し, 以下のようにポインタ p, q, r にアドレスを代入して p, q, r を使って配列 a の各要素の値とポインタ (p+i), (q+i), (r+i) のアドレスを 表示せよ. ただし, 配列 a の各要素を表示するときはポインタ表現をつかい p[j] などという表現は使ってはいけない.
また問題ごとに用いたポインタ表現について, なぜそのようなポインタ表現を用いると配列の値が表示されるのか考察で述べよ.

int *p = &a[0][0]
int *q = a[0]
int (*r)[4] = a

そこで

#include <stdio.h>

int main(void){

int a[3][4]={{11,12,13,14},
	     {21,22,23,24},
	     {31,32,33,34}}; 
int *p  ;

p=&a[0][0];
printf("a[0][0]の値=%d,a[0][0]のアドレス=%p\n",*p,p);
printf("a[0][1]の値=%d,a[0][1]のアドレス=%p\n",*(p+1),p+1);
printf("a[0][2]の値=%d,a[0][2]のアドレス=%p\n",*(p+2),p+2);
printf("a[0][3]の値=%d,a[0][3]のアドレス=%p\n",*(p+3),p+3);
printf("a[1][0]の値=%d,a[1][0]のアドレス=%p\n",*(p+4),p+4);
printf("a[1][1]の値=%d,a[1][1]のアドレス=%p\n",*(p+5),p+5);
printf("a[1][2]の値=%d,a[1][2]のアドレス=%p\n",*(p+6),p+6);
printf("a[1][3]の値=%d,a[1][3]のアドレス=%p\n",*(p+7),p+7);
printf("a[2][0]の値=%d,a[2][0]のアドレス=%p\n",*(p+8),p+8);
printf("a[2][1]の値=%d,a[2][1]のアドレス=%p\n",*(p+9),p+9);
printf("a[2][2]の値=%d,a[2][2]のアドレス=%p\n",*(p+10),p+10);
printf("a[2][3]の値=%d,a[2][3]のアドレス=%p\n",*(p+11),p+11);

int *q;
q=a[0];
printf("a[0][0]の値=%d,a[0][0]のアドレス=%p\n",*q,q);
printf("a[0][1]の値=%d,a[0][1]のアドレス=%p\n",*(q+1),q+1);
printf("a[0][2]の値=%d,a[0][2]のアドレス=%p\n",*(q+2),q+2);
printf("a[0][3]の値=%d,a[0][2]のアドレス=%p\n",*(q+3),q+3);
printf("a[1][0]の値=%d,a[1][0]のアドレス=%p\n",*(q+4),q+4);
printf("a[1][1]の値=%d,a[1][1]のアドレス=%p\n",*(q+5),q+5);
printf("a[1][2]の値=%d,a[1][2]のアドレス=%p\n",*(q+6),q+6);
printf("a[1][3]の値=%d,a[1][3]のアドレス=%p\n",*(q+7),q+7);
printf("a[2][0]の値=%d,a[2][0]のアドレス=%p\n",*(q+8),q+8);
printf("a[2][1]の値=%d,a[2][1]のアドレス=%p\n",*(q+9),q+9);
printf("a[2][2]の値=%d,a[2][2]のアドレス=%p\n",*(q+10),q+10);
printf("a[2][3]の値=%d,a[2][3]のアドレス=%p\n",*(q+11),q+11);

int (*r)[4];
r=&a[0];

printf("a[0][0]の値=%d,a[0][0]のアドレス=%p\n",*(*r),*r);
printf("a[0][1]の値=%d,a[0][1]のアドレス=%p\n",*(*r+1),*r+1);
printf("a[0][2]の値=%d,a[0][2]のアドレス=%p\n",*(*r+2),*r+2);
printf("a[0][3]の値=%d,a[0][3]のアドレス=%p\n",*(*r+3),*r+3);
printf("a[0][0]の値=%d,a[1][0]のアドレス=%p\n",*(*r+4),*r+4);
printf("a[0][1]の値=%d,a[1][1]のアドレス=%p\n",*(*r+5),*r+5);
printf("a[0][2]の値=%d,a[1][2]のアドレス=%p\n",*(*r+6),*r+6);
printf("a[0][3]の値=%d,a[1][3]のアドレス=%p\n",*(*r+7),*r+7);
printf("a[0][0]の値=%d,a[2][0]のアドレス=%p\n",*(*r+8),*r+8);
printf("a[0][1]の値=%d,a[2][1]のアドレス=%p\n",*(*r+9),*r+9);
printf("a[0][2]の値=%d,a[2][2]のアドレス=%p\n",*(*r+10),*r+10);
printf("a[0][3]の値=%d,a[2][3]のアドレス=%p\n",*(*r+11),*r+11);

return 0;
}


というプログラムを作り、実行結果も正解と同じ値が得られました。
しかし、このプログラムでは単純すぎると思い、腑に落ちません。
この他に正解が得られるポインタの使い方があればご指摘願います。

Re:ポインタと配列について(初心者です)2

Posted: 2009年6月16日(火) 14:48
by 御津凪
この問題文において、

> なぜそのようなポインタ表現を用いると配列の値が表示されるのか考察で述べよ.

ここが重要です。
なぜ、そのようにして表示できたのかを考え、文章にする必要があります。

Re:ポインタと配列について(初心者です)2

Posted: 2009年6月16日(火) 16:51
by toyo
別解ですがrの場合は配列の要素がそのまま使えますね
printf("a[1][0]の値=%d,a[1][0]のアドレス=%p\n",*(*(r+1)+0),*(r+1)+0);
	printf("a[1][1]の値=%d,a[1][1]のアドレス=%p\n",*(*(r+1)+1),*(r+1)+1);
	printf("a[1][2]の値=%d,a[1][2]のアドレス=%p\n",*(*(r+1)+2),*(r+1)+2);
	printf("a[1][3]の値=%d,a[1][3]のアドレス=%p\n",*(*(r+1)+3),*(r+1)+3);

Re:ポインタと配列について(初心者です)2

Posted: 2009年6月16日(火) 16:54
by box
>質問者さん

> しかし、このプログラムでは単純すぎると思い、腑に落ちません。

プログラムは単純であればあるほど、
読む人が理解しやすく、後から修正しやすいと思いませんか?

単純に書けるところをことさらややこしくする必要は、全くないと思います。
いかがでしょうか。

Re:ポインタと配列について(初心者です)2

Posted: 2009年6月16日(火) 17:28
by やそ
皆さんの言うとおり、プログラムは単純であればあるほど良いです。

見やすいし、わかりやすくて先生思いのプログラムじゃないかな(笑)

で、この問題の一番の肝は御津凪さんも言われているとおりで、

> なぜそのようなポインタ表現を用いると配列の値が表示されるのか考察で述べよ.

を考え、文章に出来るくらいには理解しているかどうかを見たいのだと思います。

いろんな本やネットなどの説明や、ここの諸先輩がたの回答を参考に整理して考えてみてください。

Re:ポインタと配列について(初心者です)2

Posted: 2009年6月16日(火) 18:15
by たくや
>>みなさま


ありがとうございました。こんな簡単に出来たことがないので不安だったのですが、この問題の肝は考察の部分ですね。

これからじっくり文章を仕上げたいと思います!