• ベストアンサー

&と配列とアドレスについて

&と配列とアドレスの関係性についての質問です。 以下のような処理を書くと、「a」「&a」「&a[0]」は全て同じ 値をさしてしまいます。 「a」と「&a[0]」が同じなのはわかりますが、「&a」も 同じというのは、なぜでしょうか。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ int main(void) {  int a[1];  printf("%d\n",a);  printf("%d\n",&a);  printf("%d\n",&a[0]);  return 0; } ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

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

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

a と &a はデータ型が違う――というのは 既に回答があるとおりでです。 さて、もともと、この場合の、a は、配列名 です。 ですから、&a は、「配列のアドレス」です。 逆に、「式中に現われる型「Tの配列」とい う左辺値は(3つの例外を除いて)、配列の 最初の要素を指すポインターに意味が格下げ になる。結果としてできるポインター の型 は「Tへのポインター」となる」 ( http://www.kouno.jp/home/c_faq/c6.html#0 ) という決まりがあるので、「配列の名前が書 かれていると、大抵の場合、配列の先頭要素 を指すポインタとして扱われるわけです。 むしろ、a とだけ書いたときに、アドレスが 得られるほうが、「ちょっと変な仕様」であ るわけです。 ちなみに、上の「3つの例外」のひとつは、 「& の引数になるとき」で、&a の a は、 配列そのものを意味します。

b_hunter
質問者

お礼

回答ありがとうございます。 わかりやすい説明ありがとうございました。

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

その他の回答 (2)

  • chie65535
  • ベストアンサー率43% (8539/19415)
回答No.3

>「a」と「&a[0]」が同じなのはわかりますが、「&a」も >同じというのは、なぜでしょうか。 「a」が「オブジェクトの先頭アドレス」を意味するからです。 「a」について、コンパイラがどういう解釈をしようが「先頭アドレスは1つ」です。 書き方によって「先頭アドレスがコロコロ変わってしまう」としたら、アドレスが信用できません(笑) 以下のように、要素数を「2以上」にしておいてから「+1」してみると、結果が変わってきます。 int main(void) { int a[10];  printf("%p\n",a); //先頭要素へのポインタに格下げ  printf("%p\n",&a); //配列そのもののポインタ  printf("%p\n",&a[0]); //先頭要素へのポインタ  printf("%p\n",a+1); //先頭要素の次、つまりa[1]のポインタ  printf("%p\n",(&a)+1); //配列そのものの次、つまり配列の最後の要素の次のポインタ  printf("%p\n",(&a[0])+1); //先頭要素の次、つまりa[1]のポインタ  return 0; }

b_hunter
質問者

お礼

回答ありがとうございます。 わかりやすい例示ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

aと&aはデータ型が違いますが先頭アドレスは同じなので同じ値になります それとポインタの表示には%dではなく%pを使います aはint*型 &aはint(*)[1]型 インクリメントすると違いがわかります #include <stdio.h> int main(void) { int a[2]; int *p = a; int (*q)[2] = &a; printf("%p\n",p); printf("%p\n",p+1); // 4増える printf("%p\n",q); printf("%p\n",q+1); // 4*2増える return 0; }

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

関連するQ&A

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

    コンパイラではちゃんと動いてます。 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)); } } }

  • registerと配列

    ある本に以下のような書き出しでプログラムが載っています。 >register付きで宣言された配列の先頭要素の値を表示(動作しない)< #include<stdio.h> int main(void) { register int x[5]; printf("x[0]の値は%dです。\n",x[0]); return 0; } 配列はコンパイルする段階で*(a+0)とポインタに変換されるとは理解しているのですが、私の環境(Red Hat Linux)では動作してしまいます。 さすがに、 printf("&x[0]の値は%pです。\n",&x[0]);とすると>registerにかかわらずポインタの値を求めています<という警告がでますが、 本では>動作しない<と書かれていますが、きちんとコンパイルも行われ>動作します< これはどの様に考えたらよいのでしょうか?宜しく願います。

  • 配列

    適当な記述ですが、次を見てください。 void roll(int *c) { int n, b2[8]; if(t<3) { for(n=0; n<8; n++) b2[n]=c[n]; for(n=0; n<8; n++) c[b2[n]]=7-n; for(n=0; n<8; n++) printf("%d",c[n]); printf("\n"); t++; roll(c); } else t=0; } int main() { int b[]={3,6,4,0,7,2,5,1}; roll(b); for(n=0; n<8; n++) printf("%d",b[n]); //36407251が表示されるようにしたい。 return(0); } rollが何の関数かは省略しますが、rollにmainのb(ポインタ?)を渡し、ある処理をして,それでmainに戻ってきた時にb[]を表示すると、36407251が表示されません。 ポインタを引数にするってことはポインタでさしてるとこをrollで操作してるわけですよね? そうすれば変わって当然だとはおもいます。 でも関数1で関数2に配列1を渡し、その関数2の中でで配列1の値が変化しても、元の関数1にもどれば配列1のまま変化していないようにするにはどうすればいいですか? やはり もう1つ配列を用意しなきゃだめなのでしょうか。

  • 配列の問題

    配列の問題です。 n個の要素を持つ一次元配列の値(変数値)をまったく逆に入れ替えるプログラムを作りたいのですが、この場合どのようにして逆を表現すればよいのかわかりません。 (nの値は読み込み、配列は奇数個でも偶数個でも使えるプログラムでなければなりません) 参考書を見ながら作ってみたのですが…だめでした。 プログラム初心者です。アドバイスお願いします。 int main(void) { int i,n; int vc[n]; printf("n個の要素を持つ一次元配列をつくる\n"); printf("nの値を入力してください\n"); scanf("%d",&n); for (i=0;i<n+1;i++) vc[i]=i+1; for (i=0;i<5;i++) printf("vc[%d]=%d\n",i,vc[i]); printf("この配列を逆に入れ替えると\n); return 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)を作成したいのですが、#の部分に何をあてはめたらいいかわかりません。 助けてください。

  • 関数から配列を返すには?

    return で配列を返すにはどうしたらよいのでしょうか。 例えば以下のような場合です。 int main (){ char Value[] = "999"; int a;  a = test(Value);  printf ("%d", a);   } int test(char *Value) { int nVal[255]; ここで nVal に適当な処理をして・・・  return Value; }  int a を配列とかにしてみましたけど、コンパイラが 通りません。 要は配列数値を main で受け取って表示したいのですが、 本日C言語はじめたところなので、教えていただければありががたいです。

  • 2次元配列を使ったC言語の九九表を作りたいんですが、方法がわかりません。

    C言語で、九九の表を作っているのですが2次配列を使わないでの方法なら出来るんですが、 2次配列を使うと出来なくなってします。 下記のように途中まで組んだのですが、どうしてもエラーがでてしまいます。 #include <stdio.h> int main(void) { int i,j,a[9][9]; printf(" "); for(i=1; i<=9; i++) printf("%3d", i); printf("\n"); for(i=0; i<9; i++){ for(j=0; j<9; j++) a[i][j]= {1,2,3,4,5,6,7,8,9},{2,4,6,8,10,12,14,16,18},{3,6,9,12,15,18,21,24,27},{4,8,12,16,20,24,28,32,36},{5,10,15,20,25,30,35,40,45,6,12,18,24,30,36,42,48,54,7,14,21,28,35,42,49,56,63},{8,16,24,32,40,48,56,64,72},{9,18,27,36,45,54,63,72,81} }; for(i=0; i<9; i++){ printf("%3d", i+1); for(j=0; j<9; j++) printf("%3d",a[9][9]); printf("\n"); } return 0; } とやったのですが…以下に書く部分が間違っているようで。 #include <stdio.h> int main(void) { int i,j,a[9][9]; printf(" "); for(i=1; i<=9; i++) printf("%3d", i); printf("\n"); for(i=0; i<9; i++){ for(j=0; j<9; j++) a[i][j]=□ } for(i=0; i<9; i++){ printf("%3d", i+1); for(j=0; j<9; j++) printf("%3d", □); printf("\n"); } return 0; } 色々調べたり、少しずつ変えながら試しているのですが、できません。 どなたかわかるかたいらっしゃいますか。間違いがわかりません… 配列を使用しなくても出来ることは、わかるのですが、配列を使うバージョンでもできるようになりたいんです。 私がしようとおもっているのは、81個分の値を先に計算し、9×9の2次元配列に格納し、次に81個の配列要素の値を出力したいのですが、 間違いと方法がわかる方いらっしゃいませんか。

  • C言語の配列について

    配列を20 定義し値を入力して合計値を出したいのですがどうすればよいのでしょうか 下のソースでエラーはおこりませんでした 何がちがうのでしょうか #include <stdio.h> int main() { int a[20]={}; int i, sum; printf("整数を入力してください:"); scanf("%d",&a); printf("\n"); for (i = 0; i < 10; i++) { sum += a[i]; } printf("sum= %d\n", sum); return 0; }

  • プログラミング 配列 合計

    配列の要素に値を読み込んで表示させるプログラムは 1#include <stdio.h> 2 3int main(void) 4{ 5 6 int i; 7 int vc[5]; 8 9 for (i = 0; i < 5; i++) 10 vc[i] =i + 1; 11 12 for(i = 0; i < 5; i++) 13 printf("vc[%d] = %d\n", i, vc[i]); 14 15 return (0); }でこれを書きなおして配列の値を合計するプログラムはどういうプログラムになるか教えていただけませんか?

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.