• ベストアンサー

二次元配列のポインタについて教えて下さい

今日はCの配列のポインタについて質問いたします、宜しくお願いします。 1次元の配列からは、 =================================== int *p , a={1,2,3}; p = &a; printf("%d\n" , p[1] ) ; printf("%d\n" , *p[1] ) ; ===================================== でaの値がとれますが、 二次元の配列では下のような書き方ではエラーになります。 何故でしょうか、どう書いてやればいいのでしょう。 ===============================================  printf("%d\n" , pbb[1][1] ) ;  printf("%d\n" , *pbb[1][1] ) ; =============================================== 宜しくお願いします。

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

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

> 要は > /* > printf(" *C[1][1] %d " , *(pC[1][1])); > */ > とあるように、二次元配列で、特定の配列要素の値を取り出したいのですが、上記の用に書くとエラーがでます、 一次元配列も二次元配列も、同じint*で扱えるはずがありません。 int (*pC)[5]; のようにして、要素の数を知らせてやらないと、コンパイラにはpC[0][4]の次がpC[1][0]になることがわかりません。 また、*(pC[1][1])という表記もおかしいです。

htgotk_001
質問者

お礼

m-take0220さん、回答ありがとうございます。 >int (*pC)[5]; #この宣言はどこのところで書いてやる書式でしょうか。 #int (*pC)[5]={1,2,3,4,5}; とか、 #int (*pC)[2][5]={{1,2,3,4,5}, {7,8,9,0,1}, {2,3,4,5,6}};   のような書き方でしょうか。 よろしくお願いします。

その他の回答 (6)

回答No.7

> >int (*pC)[5]; > #この宣言はどこのところで書いてやる書式でしょうか。 元のソースで int *pC; となっている部分を置き換えるだけです。 あとは、 pC = C; としてやれば、各要素にpC[i][j]の形でアクセスできるはずです。

htgotk_001
質問者

お礼

m-take0220さん、有り難うございます。 何とかできました。

  • 7o8
  • ベストアンサー率55% (5/9)
回答No.6

解決にはなっていなく申し訳ないのですが、2次元配列をポインタに渡す際は 1次元配列で書き直すのも一つの手です。 ってことで、私なら単純にこーします。 printf(" *C[1][1] %d " , pC[1*5+1]); 因みにpCへのC先頭アドレスの渡し方は「pC = &C[0][0];」が正しいです。 「pC = &C ;」の行はかなり怪しいアドレスが入る可能性がありますし、 そもそも意図が分かりません。 #まだpC = C ;の方が意図はわかります。(^_^;;;

noname#96502
noname#96502
回答No.5

>#int (*pC)[5]={1,2,3,4,5}; とか、 そう思うなら実際にコンパイルしてみたらいいですよ。 せめて試してから質問して欲しいです。 一番の勉強は自分でコンパイルさせて(エラーがでるならどこが悪いのか考えて)、デバッグしで動作を確認する事です。 人が作ったプログラムを動かしてもあまり意味がないです。

noname#96502
noname#96502
回答No.3

代理回答 ポインタのアドレスを正しく出力できているのに、ポインタが指し示す実データの出力が出来ていないだけです。 printf(" *C[%d][%d] %p " , i , j, pC+k); //アドレスの出力 printf(" C[%d][%d] %p " , i , j, *(pC+k)); //中身の出力 これで思ったプログラムになるはずです。(検証はしてません。) ポインタを使ってますが、ポインタとは何かもう一度考えたほうがよさそうですね。 >pC = &C ; この無駄コードがとても心配です。 コンパイラに依存するかもしてませんが、恐らく意図した動きはしません。意図して書く人のプログラムは修正するのは油断できなさそうなので、ちょっと尻込みします。 ポインタはC言語最大の難関です。理解している気になって理解できていない人も意外といますので、がんばってください。 また理解できたからといって無駄にポインタを使いまくるのも辞めといたほうが無難です。

htgotk_001
質問者

お礼

bravheartさん、回答ありがとうございます。 >printf(" C[%d][%d] %p " , i , j, *(pC+k)); //中身の出力 #中身の出力を 「printf(" C[%d][%d] %p " , i , j, *(pC[][])); のような通常(?)の配列形式で書いて出力をさせてやりたいのです。その書式があれば知りたいのですが、そのような書き方はできないのでしょうか。 よろしくお願いします。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

提示されたソースは、お手元にあるものと 本当に同じですか?ちゃんと全部をコピー&ペーストしていますか? kの定義がないため、コンパイルが通りません。 必要なヘッダーファイルのインクルードもありませんしね。 それから、「何をしたときにどんな」エラーが出るかの提示はナシですか?

htgotk_001
質問者

お礼

asuncionさん、何度もすみません、宜しく尾根がします。 要は /* printf(" *C[1][1] %d " , *(pC[1][1])); */ とあるように、二次元配列で、特定の配列要素の値を取り出したいのですが、上記の用に書くとエラーがでます、 エラーの出ない書き方を知りたいだけなのですがで、、、 =============================================================== #include <stdio.h> int main() { int i , j ; int k = 0; int C[5][5] ; int *pC ; printf("\n\n") ; for(i = 0 ; i < 2 ; i ++) { for( j = 0 ; j < 5 ; j ++) { k ++ ; C[i][j] = k ; printf(" C[%d][%d] %d " , i , j, C[i][j]); } printf("\n"); } pC = &C ; pC = &C[0][0]; printf("\n\n") ; k = 0 ; for(i = 0 ; i < 2 ; i ++) { for( j = 0 ; j < 5 ; j ++) { k ++ ; printf(" *C[%d][%d] %p " , i , j, pC+k); //アドレスの出力 } printf("\n"); } printf("\n\n") ; pC = &C ; k = 0 ; for(i = 0 ; i < 2 ; i ++) { for( j = 0 ; j < 5 ; j ++) { printf(" *C[%d][%d] %d " , i , j, *(pC+k)); k ++ ; } printf("\n"); } /* printf(" *C[1][1] %d " , *(pC[1][1])); */ return 0; }

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

>int *p , a={1,2,3}; このaの定義は間違っていますね。 配列になっていないです。 > printf("%d\n" , pbb[1][1] ) ; > printf("%d\n" , *pbb[1][1] ) ; pbbを定義している箇所とセットで見せてください。 それから、「エラーになる」だけではなく、 「何をしたときにどんな」エラーが出るかを具体的に書いてください。 ここを見ている人たちには超能力者はいません。 質問者さんが出してくる情報「だけ」が頼りです。

htgotk_001
質問者

お礼

asuncionさん、回答有り難う御座います、配慮が足りなかったです、宜しくお願い致します。 ============================================================ int main() { int C[5][5] ; int *pC ; printf("\n\n") ; for(i = 0 ; i < 2 ; i ++) { for( j = 0 ; j < 5 ; j ++) { k ++ ; C[i][j] = k ; printf(" C[%d][%d] %d " , i , j, C[i][j]); } printf("\n"); } pC = &C ; printf("\n\n") ; k = 0 ; for(i = 0 ; i < 2 ; i ++) { for( j = 0 ; j < 5 ; j ++) { k ++ ; printf(" *C[%d][%d] %p " , i , j, pC+k); } printf("\n"); } pC = &C ; k = 0 ; for(i = 0 ; i < 2 ; i ++) { for( j = 0 ; j < 5 ; j ++) { printf(" *C[%d][%d] %d " , i , j, *(pC+k)); k ++ ; } printf("\n"); } printf(" *C[1][1] %d " , *(pC[1][1])); return 0; }

関連するQ&A

  • 2次元配列とポインタ配列の違い

    2次元配列とポインタ配列の違いを比較するプログラムを作成したつもりなのですが、下のプログラムの printf("we[%d]=%u\n",i,&we[i][0]); という文がどうやら違うらしいのですが、全く分かりません。 なので、なんとなくでも構わないので分かる方がいらっしゃったらお願いします。 #include<stdio.h> int main(void) { int i; char *we[]={"Monday","Tuesday","Wednesday"}; char ek[][10]={"Monday","Tuesday","Wednesday"}; printf("2次元配列で格納したアドレス\n"); for(i=0;i<3;i++){ printf("ek[%d]=%u\n",i,&ek[i]); } printf("ポインタ配列のアドレス\n"); for(i=0;i<3;i++){ printf("we[%d]=%u\n",i,&we[i]); } printf("ポインタ配列で格納したアドレス\n"); for(i=0;i<3;i++){ printf("we[%d]=%u\n",i,&we[i][0]); } printf("ポインタ配列で格納した文字列\n"); for(i=0;i<3;i++){ printf("we[%d]=\%s\n",i,we[i]); } printf("2次元配列で格納した文字列\n"); for(i=0;i<3;i++){ printf("ek[%d]=\%s\n",i,ek[i]); } return(0); }

  • ポインタと二次元配列

    二次元配列a[ ][ ]の第1行の要素以後を0にするプログラムで動きます。 疑問なんですが、4行目のa[ ][4]は、なぜ[ ]のように空欄になっているんでしょうか。 また、8行目のpa=a[1];は、なぜpa=a[0];ではだめなんでしょうか。第1行は先頭行で0行目を意味しているのではないでしょうか。 #include <stdio.h> void main(void) /*ポインタと二次元配列*/ { static int a[ ][4]={{1,2,3,0}, {4,5,6,0}, {7,8,9,-999}}; int j,k,*pa; pa=a[1]; while(*pa!=-999){ *pa=0; pa++; } for(j=0;j<3;j++){ for(k=0;k<4;k++) printf("%5d",a[j][k]); printf("\n"); } }

  • 助けてください ポインタと配列

    #include <stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 0}; int i, *ptr; ptr = &a[0]; while (*ptr!= 0){ if(*ptr!=0) *ptr=0; } for (i = 0; i < 5; i++) printf("a[%d]=%2d &a[%d]=%p\n",i,a[i],i,ptr); // 配列aの値とアドレスを表示せよ putchar('\n'); ptr = &a[0]; for (i = 0; i < 5; i++){ printf("ptr値 =%d ptrアドレス =%p \n",*ptr,ptr); ; } // ポインタptr を使用して、修正後の配列aの値とアドレスを表示せよ printf("\n"); return (0); } /* 処理結果 a[0]= 0 &a[0]=0013FF3C a[1]= 2 &a[1]=0013FF3C a[2]= 3 &a[2]=0013FF3C a[3]= 4 &a[3]=0013FF3C a[4]= 0 &a[4]=0013FF3C ptr値 =0 ptrアドレス =0013FF3C ptr値 =0 ptrアドレス =0013FF3C ptr値 =0 ptrアドレス =0013FF3C ptr値 =0 ptrアドレス =0013FF3C ptr値 =0 ptrアドレス =0013FF3C 続行するには何かキーを押してください . . .*/ 一次元配列a[]の一番目の要素以外を0にするプログラムを作成せよ。 ただし、最後の要素は0とする。 上記の問題文とこの結果は合致しているでしょうか?

  • ポインタと配列 助けてください

    #include <stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 0}; int i, *ptr; ptr = ######; while (*ptr != 0){ ######; ######; }      for (i = 0; i < 5; i++) printf("a[%d]=%2d &a[%d]=%p\n", i, #####,i, #####); putchar('\n'); ptr = ######; for (i = 0; i < 5; i++){ printf("ptr値 =%d ptrアドレス =%p \n", ####, ####); ####; } printf("\n"); return (0); } 一次元配列a[]の一番目の要素以外を0にするプログラム(ただし、最後の要素は0)を作成したいのですが、#の部分に何をあてはめたらいいかわかりません。 助けてください。

  • C言語、配列とポインタとアスタリスクの関係

    ちょっと行き詰まっています。 苦しんで覚えるCで勉強しているのですが、まさに苦しんでいます。 http://9cguide.appspot.com/19-01.html #include <stdio.h> #include <stdlib.h> int main() { int i; int *heap; heap = (int *)malloc(sizeof(int) * 10); if (heap == NULL) exit(0); for (i = 0;i < 10;i++) { heap[i] = i; } printf("%d\n",heap[5]); free(heap); return 0; } int *heap; ここで int ポインタを宣言しています。 heap = (int *)malloc(sizeof(int) * 10); ここでヒープを確保しています。(int *) のキャストも sizeof(int) も理解できました。 for (i = 0;i < 10;i++) { heap[i] = i; } まず1点目の疑問はここです。 変数 heap は「ポインタ変数」です。それでいて配列です。 ポインタ変数は、プログラムの文中で通常の変数として使うときには「*heap」のように先頭にアスタリスクを付けなければならかなったと記憶しています。 アスタリスクなしの「heap」はアドレス格納用の変数ではないでしょうか。 printf("%d\n",heap[5]); そして、その疑問をよそに、この命令が成り立っているようです。 画面上に出される結果は「5」であり、変数「heap」がただの配列として機能しているように見えます。 この printf 次のように書き換えると、エラーが出てコンパイルできませんでした。 書き換え実験1 printf("%p\n",*heap[5]); アスタリスクを付けて、通常の変数として扱い、受ける方も「%d」から「%p」に書き換えてアドレスを表示してみようと思ったのですが、 「「pointer」を付け忘れています。」というエラーが表示されました。 書き換え実験2 printf("%p\n",heap[5]); 受ける方を「%d」からポインタを受ける「%p」にしましたが、変数の方はアスタリスクなしです。 すると、結果はアドレス「00000005」が返ってきました。 (変数にアスタがないのになぜ?) 書き換え実験3 printf("%d\n",*heap[5]); これはもうめちゃくちゃですが、一応やってみました。コンパイルエラーで、 「「pointer」を付け忘れています。」というエラーが表示されました。 つまり、こういうことです。 0:printf("%d\n",heap[5]); //5 1:printf("%p\n",*heap[5]); //エラー 2:printf("%p\n",heap[5]); //00000005 3:printf("%d\n",*heap[5]);//エラー この結果から推測するに、アスタリスクはそもそも付けるとエラーになり、アドレスを表すか、そのアドレスに格納された値を表すかを切り替えるには、単にその変数を受ける「%d」や「%p」を変えるだけ、ということになるのだと思います。 mallocで返ってくるのは、ポインタ変数(の配列)だと思うので、変数のモードを切り替えるためにアスタリスクが必要なのだと思っていましたが、どこかで重大な勘違いをしているようです。 この件について、どなたか教えていただけないでしょうか。

  • できているとは、思うのですが。ポインタの配列を

    コンパイラではちゃんと動いてます。 1 2 3 0 1 2 3 という具合です。 気になるのは、printarrayの部分が正しいのか、ちょっと悩んでいます 問題としては main関数では0の値を読み込むまで最大99(MAX-1)個の値を配列 xに読み込んでいる。引数のポインタからの値を、値が0になるまで すべて1行に1つづつ画面に出力する関数printarray()を作成し、 プログラムを完成せよ。 引数はアドレスとして受け取る事。(配列としてでなく) フォーマットは、 "%d¥n" とする。(余計な出力はしない事。) (0は出力しない。) main内部を変更してはならない。 以下がソースです。 ご指摘よろしくお願いします。 #include <stdio.h> #define MAX 5 void printarray(int *); int main() { int x[MAX], i; int *p; x[MAX-1] = 0; for (i = 0, p = x; i < MAX-1; ++i, ++p) { scanf("%d", p); if (*p == 0) { break; } } printarray(x); return 0; } void printarray(int *a) { int i,*p; for(i = 0, p = a; i < MAX-1; ++i,++p) { if(*p == 0){ // continue; break; }else{ printf("%d\n", *(a+i)); } } }

  • 2次元配列のポインタ

    整数型行2列2の2次元配列の[1][0]は、ポインタでは3になるとおもっているのですが、ちがったでしょうか? 下記のソースでエラーが出ていて困っています。 void main() { int array[2][2] = { { 9, 9 }, { 9, 9 } }; int num=2, j,i; *(array + 3) = 0; for (i = 0; i < num; i++) { for (j = 0; j < num; j++) { printf("%d", array[i][j]); } puts(""); } } 99 09 と表示させたいのですが、どこに間違いがあるのでしょうか?

  • ダブルポインタで2次元配列を作成

    2次元配列を作り、そのアドレスなどを表示させましたが どうもおかしいです。 3行5列の配列で、3本のポインタ配列がありますが、 その配列のアドレスがかぶっているのです。 まずはコンパイルしてみてください。 #include<stdio.h> main() { int i; int k; int y=1; int **p; p=(int **)malloc(sizeof(int *)*3); for(i=0;i<=2;i++) { *(p+i)=(int *)malloc(sizeof(int)*5); } for(i=0;i<=2;i++){ for(k=0;k<=4;k++){ p[i][k]=(i+k)*y; } y=y*10; } for(i=0;i<=2;i++){ for(k=0;k<=4;k++){ printf("%4d",*(*(p+i)+k)); } printf("\n"); } printf("\n"); for(i=0;i<=2;i++) { printf("%p\n",p+i); } printf("\n"); for(i=0;i<=2;i++) { printf("%p\n",&p+i); } printf("\n"); for(i=0;i<=2;i++) { printf("%p\n",*(p+i)); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",*(p)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&*(p)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&**(p)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",*(p+1)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&*(p+1)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&**(p+1)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",*(p+2)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&*(p+2)+i); } printf("\n"); for(i=0;i<=4;i++) { printf("%p\n",&**(p+2)+i); } printf("\n"); for(i=0;i<=2;i++){ for(k=0;k<=4;k++){ printf("%p\n",&*(*(p+i)+k)); }} free(p); return 0; } どこがかぶっているかと申しますと、 for(i=0;i<=4;i++) { printf("%p\n",&*(p)+i); } と for(i=0;i<=4;i++) { printf("%p\n",&*(p+1)+i); } と for(i=0;i<=4;i++) { printf("%p\n",&*(p+2)+i); } です。 これが同じアドレスになるはずは論理的にありえないことです。 VC++2008無料バージョンです。 よろしくお願いいたします。

  • 配列とポインタ

    配列を以下のように宣言をして int t[3][3] ={{12,34,45},{11,45,65},{76,85,25}}; p=&t[1][0]; printfで以下のように出力したのですが printf("1:%d \n", (*p+1)); printf("2:%d \n", (*p+1)); 両方とも出力結果が12になります 12,13のようになると思ったのですが どこがいけないのでしょうか?? どなたかよろしくお願いします<(_ _)>

  • ポインタ配列

    配列をポインタでとって、配列要素を足していこうと思ったのですが、 #include <stdio.h> int main (void) { int p[11]={11,23,43,66,54,67,51,88,22,43,-1}; int *e=p; int x=0; int i=0; while( *e!=-1 ) { x + = ( * (e+i) ); i++; } printf("%d\n",x); return 0; } x = ( * ( e+i ) ); ↑この部分がなぜだめなのか理解できません どなたか教えてくださるとありがたいです

専門家に質問してみよう