Cの配列についての質問

このQ&Aのポイント
  • Cの配列についての質問についての要約文です。
  • C言語の配列における数字の表示が変な数字になる原因について説明します。
  • gcc4.6.3とubuntu 12.04の環境下でのC言語の配列の表示に関する質問です。
回答を見る
  • ベストアンサー

Cの配列についての質問

Cオープンコースウェア9-4の問題を改変した質問 #include <stdio.h> void set (int b[],int n,int dat){ int i; for (i= 0;i<n;i++){ b[i] = dat; } } int main(){ int a[4][6] int i,j,M= 4,N=6; set ((int *)a,sizeof(a)/sizeof(a[0][0]),1) for (i = 0;i<M;i++){ for (j= 0;j<N,j++){ printf("%2d",a[i][j]); } printf("\N"); } return 0; } ここまで このmein関数内の表示部分を変更して for (i =0;i<(sizeof(a)/sizeof(a[0][0]));i++){ printf("%2d",(int *)a); } のようにすると変な数字になってしまうのはなぜでしょうか? 環境はgcc4.6.3 ubuntu 12.04です

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

  • ベストアンサー
noname#208507
noname#208507
回答No.8

> 少しずれてしまいますが、お行儀が悪いというのはどういった点ででしょうか? このアクセス方法を習慣にしてしまうのは良くありません。 データ型はプログラムの整合性を保つのに重要な役目を果たすので、キャストは避けるべきです(興味があれば「ラッセルのパラドックス」を調べてみてください)。 メモリ上の連続した領域に二次元配列が確保されるので一次元配列のようにアクセスできますが、保守のしやすさやバグの混入を予防するならfor文を入れ子にし、a[i][j] のように本来の二次元配列としてアクセスした方が良いと思います。プログラマの良心として。

pipopipoid
質問者

お礼

ありがとうございました。 ラッセルのパラドクスをとりあえず理解しましたが 今回の件までどう関係するかはわかりません。 とりあえず、保守性に欠けるというのは かなりわかりやすく、そのようなことがないよう頑張っていきたいと思います。

その他の回答 (7)

回答No.7

#6の回答に示したコードの訂正です。 int *b, *be=&a[0][0]+(sizeof a / sizeof(int)); for ( b=&a[0][0]; b<be; b++ ) printf("%2d", *b);

pipopipoid
質問者

お礼

下よんでわからなかったんですが、とてもわかりやすくなっていますね。これなら理解できるかと思います。 ありがとうございます。

回答No.6

#5の回答のコードを、[]を使わないで for (i =0;i<(sizeof(a)/sizeof(a[0][0]));i++){   printf("%2d", *((int *)a+i) ); } と書いても同じです。 私なら、二次元配列のすべての要素を一重のforループで参照したければ、たとえば、 int *b, *be=b+(sizeof a / sizeof(int)); for ( b=&a[0][0]; b<be; b++ ) printf("%2d", *b); のようにします。

pipopipoid
質問者

お礼

後半部分がかなり僕には難しいので、いろいろテストして理解を深めようと思います。ありがとうございました。

noname#208507
noname#208507
回答No.5

> 下に書いたように(int)*aの書き間違いでしたが、 *a の値は a[0] と同じです。そして a は二次元配列です。なので a[0] は一次元配列の先頭アドレスになります。つまりそれが「変な数字になってしまう」理由です。 下のように強制的に一次元配列であるかのように扱えば、お望みの結果が得られるでしょう(あまり行儀が良い方法とは言えませんが)。  for (i =0;i<(sizeof(a)/sizeof(a[0][0]));i++){   printf("%2d", ((int *)a)[i]);  }

pipopipoid
質問者

お礼

ありがとうございます。 このようなループにできないか考えていました。 少しずれてしまいますが、お行儀が悪いというのはどういった点ででしょうか?

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

正しいプログラムはどうなっているのでしょうか? 全て出してください. あと, その場合どのような数字が出ているのでしょうか?

pipopipoid
質問者

お礼

実現できる、というのはmain関数内でできるということです。口下手で申し訳ありません。

pipopipoid
質問者

補足

ここまでと書いているところまではそのままです。 \Nと\nを間違えている部分については\nが正しいです。 それ以降のプログラムは(3行ですが)自分で考えた部分です。 後出しになるのは困るのでここで言っておかなければならないのは、 setの部分に for (i= 0;i<n;i++){ printf("%d",b[i]) } と書くと1が26並ぶので、同じ動作をiとaだけで実現できるか知りたいだけなのです。

noname#208507
noname#208507
回答No.3

変な数字に見えるのはメモリのアドレスだからです。配列の名前はその配列の先頭アドレス、つまりメモリ上のどの番地から配列が始まるか、を返します。 この数字はデータの存在する場所を意味し、配列に代入した値(この場合は1)とは無関係です。 また、printf("%2d",(int *)a);でアドレスを10進数の整数で表示していますが、一般的にはアドレスの表示に printf(" %p",a); を用います(お使いの環境では配列のアドレスが16進数で表示されます)。for文で繰り返しても、単に a だけではいつも先頭アドレスを返すので、繰り返し同じアドレスが表示されるだけです。 該当部分を下のようにすると、a[i][j]のアドレスと、配列に代入した値の関係が分かりやすいでしょう。  for (i = 0;i<M;i++){   for (j= 0;j<N;j++){    printf(" %p=%p:%d=%d", &a[i][j], ((*(a+i))+j), a[i][j], *((*(a+i))+j));   }   printf("\n");  }

pipopipoid
質問者

補足

下に書いたように(int)*aの書き間違いでしたが、 残念なことにちょうど同じタイミングで書いてしまったようですね。 *((*(a+i))+j)が目的とするものに近いです。 この部分を1つの変数で表す(set()と同じように)するにはどうすればいいかを考えて、現在困っています

  • k_kota
  • ベストアンサー率19% (434/2186)
回答No.2

これが何を表示しようとしているのか理解していますか? 何を表示しようとしているのか補足して下さい。 そこが合ってないと変な数字の何が変なのかがはっきりしません。 まあ、ポインタ型を整数で出力したらまともな値はでない気がします。

pipopipoid
質問者

お礼

目的というか、予想したのは1が26回続く出力です

pipopipoid
質問者

補足

下にも書きましたが、(int *)aは(int) *aの間違いです

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

何を表示しようと思ってそのように変更したのでしょうか? そして, それで何を表示しているのか理解できていますか? あと, printf("\N"); はおかしいと思うよ.

pipopipoid
質問者

お礼

上に書き忘れてしまったので。 111111 111111 111111 111111 が本来の結果として得られます

pipopipoid
質問者

補足

上のset()で配列の数によらないようにsizeofを用いて、かつ1次配列のように扱ったので、main関数内でも1次配列のようにしてa[][]を出力できるか調べようとしていました。 書き写し間違いなのですが、最後の部分が(int)*aとしたのの間違いです 直接のコピーではないので、いろいろ書き間違えています

関連するQ&A

  • C言語の配列の使い方について質問です。

    以下のプログラムを配列を使って見やすくしたいのですが、どのように作ったら良いでしょうか? 宜しくお願いします。 #include<stdio.h> int main(void) { int a, b, c, d, e, f, g, h, i, j, k, l, m ,n, o; /*5段目の処理*/ for(a = 1; a <= 15; a++) { for(b = 1; b <= 15; b++) { if(a == b) continue; for(c = 1; c <= 15; c++) { if(a == c || b == c) continue; for(d = 1; d <= 15; d++) { if(a == d || b == d || c == d) continue; for(e = 1; e <= 15; e++) { if(a == e || b == e || c == e || d == e) continue; // printf("%d %d %d %d %d\n", a, b, c, d, e); ////4段目//// if(a>b){ f=a-b; } else if(a<b){ f=b-a; } if(b>c){ g=b-c; } else if(b<c){ g=c-b; } if(c>d){ h=c-d; } else if(c<d){ h=d-c; } if(d>e){ i=d-e; } else if(e<d){ i=e-d; } // printf(" %d %d %d %d \n", f, g, h, i); /////3段目//// if(f>g){ j=f-g; } else if(f<g){ j=g-f; } if(g>h){ k=g-h; } else if(g<h){ k=h-g; } if(h>i){ l=h-i; } else if(h<i){ l=i-h; } // printf(" %d %d %d \n", j, k, l); /////2段目//// if(j>k){ m=j-k; } else if(j<k){ m=k-j; } if(k>l){ n=k-l; } else if(k<l){ n=l-k; } // printf(" %d %d \n", m, n); /////三段目///// if(m>n){ o=m-n; } else if(m<n){ o=n-m; } // printf(" %d \n", o); if(a != b != c != d != e != f != g != h != i != j != k != l != m != n != o){ printf("%d %d %d %d %d\n", a, b, c, d, e); printf(" %d %d %d %d \n", f, g, h, i); printf(" %d %d %d \n", j, k, l); printf(" %d %d \n", m, n); printf(" %d \n", o); } } } } } } }

  • C言語 2次元配列の積について

    <演習>  4行3列の行列と3行4列の行列の積を求めるプログラムを作成    せよ。各構成要素の値はキーボードから読み込むこと。  ここに出てくる「行列」とは、数学で出てくるあの「行列」のこと でしょうか。  そうなると私が作成したプログラムは意味が違ってきます。 4回同じ事をする様になっていて1回分の計算結果だけにしたいのですが、方法が分かりません。  入門レベルの知識しかありません。ご指導の程、お願いしたいで す。 下記、プログラムを送付します。 <プログラム> #include <stdio.h> int main(void) { int i,j=0; int o,p; int a[4][3]; int b[3][4]; int m[4][4]; for (i = 0;i < 4; i++){ for (j = 0; j < 3 ; j++) { printf("a[%d][%d] = ",i,j); scanf("%d",&a[i][j]); } } printf("\n"); for (i= 0; i < 3; i++){ for (j = 0; j < 4; j++){ printf("b[%d][%d] = ",i,j); scanf("%d",&b[i][j]); } } printf("\n"); for (o = 0; o < 4; o++){ for (p = 0; p < 4; p++){ for (j = 0; j < 4; j++){ for ( i=0 ; i < 4 ;i++ ) { m[o][p] = a[i][j] * b[i][j]; printf ("a[%d][%d] = %d ," ,i, j, a[i][j]); printf ("b[%d][%d] = %d ," ,i, j, b[i][j]); printf("m[%d][%d] = %d \n",o,p,m[o][p]); } } } } return 0; }    

  • C++についての質問です

    プログラミング初心者です 以下の通りに正方行列の積を求めるプログラムを作成したのですが、うまくいきません。 #include<stdio.h> #define DTM 20 void InputMatrix(double[][DTM], int, char); void PrintMatrix(double[][DTM], int, char); void MatrixMulti(double[][DTM], double[][DTM], double[][DTM], int); int main(void) { double matrixA[DTM][DTM]; double matrixB[DTM][DTM]; double matrixC[DTM][DTM]; int n; printf("正方行列の積を求めるプログラムです\n"); printf("正方行列の次元を入れてください(<=20):"); scanf_s("%d", &n); InputMatrix(matrixA, n, 'A'); InputMatrix(matrixB, n, 'B'); MatrixMulti(matrixA, matrixB, matrixC, n); printf("\n行列 C =A×B\n"); PrintMatrix(matrixC, n, 'C'); return 0; } void InputMatrix(double a[][DTM], int n, char ch) { int i, j; printf("行列 %cの入力\n", ch); for (i = 0; i < n;i++) { for (j = 0;j < n;j++) { printf("%c[%d][%d] =", ch, i + 1, j + 1); scanf_s("%lf", &a[i][j]); } } } void PrintMatrix(double a[][DTM], int n, char ch) { int i, j; printf("行列 %c の出力\n", ch); for (i = 0;i < n;i++) { for (j = 0;j < n;j++) { printf("%5.2f\t", a[i][j]); } printf("\n"); } } void MatrixMulti(double a[][DTM], double b[][DTM], double c[][DTM], int n) { int i, j, k; for (i = 0;i < n;i++) { for (j = 0;j < n;j++) { c[i][j] = 0; for (k = 0;k < n;k++) { c[i][j] =a[i][k] * b[k][j]; } printf("%5.2f\t",c[i][j]); } printf("\n"); } }

  • 二次元配列に関する質問です。

    一次元配列はわかるのですが二次元配列になると、わからない時があります。 <ソース> #include<stdio.h> int main() { int dat[2][5]={1,2,3,4,5,6,7,8,9,10}; int i; int j; for(i=0;i<2;i++){ for(j=0;j<5;j++){ printf("dat[%d][%d] %d\n",i,j,dat[i][j]); } } return 0; } このプログラムでわからないのは、 int dat[2][5]={1,2,3,4,5,6,7,8,9,10};の部分です。 普段は、int dat[2][5]={{1,2,3,4,5}, {6,7,8,9,10}, }; という使い方をしているのですが・・・。 どうちがうのでしょうか?

  • c言語 行列のn階乗のプログラム

      1 2 -1 D= 3 0 -2   -1 1 2 の3次正方行列のn乗を計算するプログラムを作成しています。 いろいろと試してみましたがうまくいきません。 どなたか教えていただけるとうれしいです。 よろしくおねがいします。 #include <stdio.h> int main(void) { int a[3][3]={ {-1,2,-1},{3,0,-2},{-1,1,2} }; int b[3][3]={ {-1,2,-1},{3,0,-2},{-1,1,2} }; int s[3][3]; int m,n; int i,j,k; printf("[A]^n;n = ");scanf("%d",&n); for (m=2;m <= n;m++){ for (i=0;i<3;i++){ for (j=0;j<3;j++){ s[i][j] = 0; for(k=0;k<3;k++){ s[i][j] =s[i][j] + a[i][k] * b[k][j]; } } } for(i=0;i<3;i++){ for(j=0;j<3;j++){ b[i][j]=s[i][j]; } } printf("%3d",s[i][j]); putchar('\n'); } return (0); }

  • c言語についての質問です

    #include<stdio.h> #define N 3 void inputAns(int *row,int *col,int data[][N]); void printAns(int ID,int data[][N]); int main(){ int row[N]={2,3,6},col[N]={8,5,3},answer[N][N]; int i,ID; printf("Input your ID number :\n"); scanf("%d",&ID);inputAns(row,col,answer); printAns(ID,answer); return(1); } void inputAns(int *row,int *col,int data[][N]){ int i,j; printf(" Input Answers of matrxi Q :\n"); for(i=0;i<N;i++){ for(j=0; j<N; j++){ printf("%2d+%2d=",row[i],col[j]); scanf("%d",&data[i][j]); } } } void printAns(int ID, int data[][N]){ FILE *fp; int i,j; fp=fopen("ans.dat","a+t"); fprintf(fp,"%d\n",ID); for(i=0; i<N; i++){ for(j=0; j<N; j++) fprintf(fp," %3d",data[i][j]); fprintf(fp,"\n"); } fclose(fp); } この百マス計算のプログラムの28行目からを書き換えて以下のような画面出力を求めたいです。 >./a.exe ID=50413001 [ 9/9 ] ID=50413002 [ 5/9 ] ID=50413003 [ 7/9 ] ID=50413004 [ 6/9 ] ID=50413005 [ 5/9 ] == correct rate === 4/5 3/5 5/5 5/5 1/5 4/5 4/5 1/5 5/5 =================== > 読み込むファイル(ans.dat)は以下のものです。 50413001 10 7 5 11 8 6 14 11 9 50413002 10 7 5 11 9 5 13 10 9 50413003 10 7 5 11 5 6 14 10 9 50413004 10 11 5 11 5 6 14 10 9 50413005 9 11 5 11 5 6 14 10 9 読み込みから集計がうまくいかず困っています。 どなたか教えてくれませんか?

  • C言語プログラム 配列

    C言語プログラム初心者です。以下のプログラムに対して、実行結果がなぜそうなるかがわからないので、詳しく教えてください。 #include<stdio.h> int func(int a[ ],int b[ ],int n); main(){ int i,k; static int a[12] ={1,2,3,4,5,(省略)・・・,12};  static int b[12] ={21,22,23,24,(省略)・・・,32}; k = func(a,b,6); k = func(b+3,a+3,6); printf("a = "); for(i=0;i<12;i++)printf("%d",a[i]); printf("\n = b"); for(i=0;i<12;i++)printf("%d",b[i]); printf("\n k = %d\n",k); } int func(int a[ ],int b[ ],int n){ int i,x=0; for(i=0;i<n;i++);{ a[i] = b[i]; x = x+a[i]; } return(x); } 結果: a = 21 22 23 .... 26 7 8 9 10 11 12 b = 21 22 23 .... 26 7 8 9 30 31 32 k = 99

  • CからVB

    以下のプログラムはC言語で作成されています。 これをVBで作成したいです。 教えてください。 #include <stdio.h> #include <stdlib.h> double *alloc(int r,int n,int m); void input(double *p,int r,int n,int m); void sumup(double *p,int r,int n,int m); int main(void){ int r, n, m; double *p; // 行列サイズ入力 printf("input r n m "); scanf("%d %d %d",&r,&n,&m); // 行列領域取得 p = alloc(r,n,m); // 行列要素入力 input(p,r,n,m); // 行列の和 sumup(p,r,n,m); //終了,行列領域解放 free(p); return 0; } double *alloc(int r,int n,int m){ double *p; printf("MATRIX[r=%d][n=%d][m=%d]\n\n",r,n,m); p = (double*)malloc(sizeof(double)*r*n*m); if( p == NULL){ printf("error! malloc failed.\n"); exit(-1); } return p; } void input(double *p,int r, int n,int m) { int i,j,k; for(i = 0; i < r; i++){ for(j = 0;j < n; j++){ for(k = 0; k < m; k++){ printf("input MATRIX[%d][%d][%d]= ",i,j,k); scanf("%lf",&p[i*(n*m)+j*m+k]); } } } printf("\n"); } // 行列の和 void sumup(double *p,int r,int n,int m){ int i, j, k; // 0.0, not 0!!! double sum = 0.0; printf("sum of %d matrices:\n",r); for(j = 0; j< n; j++){ for(k = 0;k < m; k++){ sum=0; for(i = 0;i < r;i++){ sum += p[i*(n*m)+j*m+k]; } printf("\n%2f",sum); } } printf("\n"); }

  • c言語について

    #include <stdio.h> MakeData(int *a,int n){ int i,b[5]={5,1,4,7,2}; for(i=0;i<5;i++){a[i]=b[i];} } BubbleSort(int n,int *a){ ここに流れ図に沿ったプログラムを作る } main(){ int i,n,a[100]; n=5; MakeData(a,n); for(i=0;i<n;i++){printf("%4d ",a[i]);}printf("¥n"); printf("並べ替え後¥n"); BubbleSort(n,a); for(i=0;i<n;i++){printf("%4d ",a[i]);}printf("¥n"); } この課題が分かりません。 もし詳しい方がいらっしゃいましたら教えて頂けると助かります。

  • C++ の多次元配列なんですが

    int i,j; int (*p)[2][3]; int *x; int a[2][3] = {{1,2,3},{4,5,6}}; p = &a; x = &a[0][0]; for ( i = 0; i < 2; i++ ) { for ( j = 0; j < 3; j++) { printf (" %d", (*p)[i][j]); } } printf (" | "); for ( i = 0; i < 2; i++ ) { for ( j = 0; j < 3; j++) { printf (" %d", *(x + ( i * 3 + j )) ); } } printf (" | "); for ( i = 0; i < 6; i++ ) { printf (" %d", *(x + i) ); } これで大丈夫でしょか?

専門家に質問してみよう