• ベストアンサー

ポインタについて

ポインタについてですが、下記のプログラムで、 data = array;  で、array[0] のアドレスを代入してますよね? for文で、all+= data[i];では、 どんな計算がおこなわれていますか? dataにarray[0]のアドレスが代入されているので、アドレスの足し算が行われているんですか?(よく解らないのですが。) 教えてください。 #include <stdio.h> int main(void) { int *data; int i, all = 0, array[10] =15,78,98,15,98,85,17,35,42,15; data = array; for (i = 0;i < 10;i++) { all+= data[i]; } printf("%d\n",all/ 10); return 0; }

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

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

式中では、配列は「配列の先頭要素へのポインタ」に読み換えられます。 つまり、  data = array; は  data = &array[0]; と書いたのと同じ事です。 (ただし、「配列の先頭要素へのポインタ」に読み換えられない例外が存在します。 例えば、sizeof演算子のオペランドになったときなど。) また、配列の要素にアクセスするときには添字演算子[ ]を用いて  p[i] このように行いますが、これは以下の式と全く同じ意味になります。  *(p+i) 同じ意味なので、全部後者の書き方にすることも可能ですが、 添字演算子[ ]を用いた方が読み書きしやすいので、 配列の要素にアクセスするときなどは普通こちらを使います。 よって、  data[0] は、  *(data+0) と等価なので、dataに配列arrayの先頭要素へのポインタが入っていれば、 data[0]で配列arrayの先頭要素にアクセスできることになります。

startover
質問者

お礼

参考になります。 どうもありがとうございました。

その他の回答 (3)

  • bnosuke
  • ベストアンサー率21% (4/19)
回答No.4

1) array は 単なるint * 型の定数です。値は &array[0] です。 2) array[i] と *(array + i) は全く等価です。 3) *(data + i) と data[i] は全く等価です。 4) 2)と3)の違いは、arrayという定数か、dataという変数か、の違いで、それ以外は本質的に全く違いはありません。ですから、機械的に置き換えることができます。 5)故に、 data == array の時、2) 3)は全て同じことを内部では行っています。

startover
質問者

お礼

かいとうありがとうございました。 参考にしてみます。

  • ddnp009
  • ベストアンサー率25% (15/58)
回答No.3

まず int array[] = {15,78,98,15,98,85,17,35,42,15}; array == &array[0]、 ・配列名は、その先頭要素を指すポインタとみなされる。 int *data = array; ・intへのポインタdataは、配列arrayの先頭要素を指す。 解釈1、  data は &array[0]の別名(alias)である。  (同じアドレスを指し、型も一致するため) 解釈2、  data は intを指す独立したポインタであり、  (たまたま)配列arrayの先頭要素を指す。 1の解釈をした場合、all += data[i] は 非常にすんなり飲み込めるでしょう。 all += array[i] と等価。 2の解釈をした場合、dataは独立した"ポインタ"なので、 data[i]とするよりも、 *(data + i)としたほうがポインタとしての働きに適いますね。 コンパイラの解釈はdata[i]も*(data + i)も一緒。

startover
質問者

お礼

参考になります。 どうもありがとうございました。

回答No.1

all+= data[i]; 右辺式は、dataの配列要素のi番目を取り出しています。 allに加算されるというだけです。 もっと細かくいうと、Cにおいて、配列とポインタは等価です。 data自体はポインタですが[ ]が付く事で配列と同じようになります。 そして、実際にはポインタdataの指す属性(ここでは、int *dataと定義されているので int)のサイズ分とインデックスiに応じた分だけポインタが加算されるということです。 まず、data=arrayとしているので、data=&array[0]の状態です。 これで、data[i]のiの値を進めると data[0]・・ポインタdataが指すint属性の値、即ちarray[0] data[1]・・ポインタdata+sizeof(int)*1 が指す位置にあるint属性の値、即ちarray[1]          : data[n]・・ポインタdata+sizeof(int)*n が指す位置にあるint属性の値、即ちarray[n] という関係です。

startover
質問者

お礼

参考になります。 どうもありがとうございました。

関連するQ&A

  • C言語の配列とポインタについて

    C言語の配列とポインタについてわからないことがあります。 以下のソース例は、10個の値の平均値を求めるプログラムです。 コメントを挟んだ部分が疑問点です。 【ソース例】 #include <stdio.h> int getaverage(int *data); int main(void) { int average,array[10] = {15,78,98,15,98,85,17,35,42,15}; average = getaverage(array); printf("%d\n",average); return 0; } int getaverage(int *data) { int i,average = 0; for (i = 0;i < 10;i++) { average += data[i]; /*ポインタ変数なのに? */ } return average / 10; } 【実行例】 49 このdata[i]はポインタ変数であり、 配列arrayの i 番目の要素であるarray[i]の"アドレス" が代入されているはずだと思うのですが、 なぜ通常の整数変数であるaverageと数値計算が出来、正しい結果が出たのでしょうか? あたかもdata[i]には、 array[i]の"アドレス"ではなく、 array[i]の"メモリの中身"が代入されているようです。 どういうことでしょうか? 回答よろしくお願いします。

  • ポインタいついて教えてください

    ポインタがわかりません。 教えてください。 下の二つは、共に「100」を表記すると思いますが、 どこがどのように違うのですか。 また、f1()という関数をつくって、ここで scanfを使って、5つぐらい値を代入させて、 他の関数でこの値を使おうと思っています。 この場合下のどちらを使うのが、よろしいのでしょうか。 よろしくお願いします #include <stdio.h> int main(void) { int *p, q; q = 100; /* q に100を代入 */ p = &q; /* p にq のアドレスを割り当てる */ printf("%d", *p); return 0; } #include <stdio.h> int main(void) { int *p, q; p = &q; /* q のアドレスを得る */ *p = 100; /* ポインタを使ってq に値を代入する */ printf("%d", q); return 0; }

  • ポインタについて

    今初めてポインタというものを勉強しております。 よろしくお願いします。 ◎1---------------------------------- #include<stdio.h> int main(void) { int mydt=1234; int *pt; pt=&mydt; printf("*pt=%d\n",*pt); printf("&mydt=%p\n",&mydt); return 0; } --------------------------------------- ◎1のようにmydtのアドレスをポインタptに代入すれば、このプログラムは正常に動きました。 ◎2----------------------------------- #include<stdio.h> int main(void) { int mydt=1234; int *pt=&mydt; printf("*pt=%d\n",*pt); printf("&mydt=%p\n",&mydt); return 0; } ---------------------------------------- ◎2で「int *pt=&mydt;」があまりどういう意味かはわかりませんが、これも正常に動きました。 ◎3------------------------------------ #include<stdio.h> int main(void) { int mydt=1234; int *pt; *pt=&mydt printf("*pt=%d\n",*pt); printf("&mydt=%p\n",&mydt); return 0; } -------------------------------------- ◎3のように◎2と違って「*pt=&mydt」の代入を後から行うと、「'=' : 'int *__w64 ' から 'int' に変換できません。」といったようなエラーが起きてしまいます。 ◎1と◎2の違い、後何故◎3はダメなのかがわかりません。 教えていただけると嬉しいです。 後補足として、配列とポインタについてですが、 ◎4------------------------------ char ss[10]="ABCDE"; char *ssp=ss; --------------------------------- ◎5---------------------------- char ss[10]="ABCDE"; char *ssp; ssp=ss; -------------------------------- ◎4と◎5も同じような事だとは思いますが違いを教えていただけると嬉しいです。 よろしくお願いします。

  • // c のポインタと配列について質問です。

    // c のポインタと配列について質問です。 //次のようなプログラムがあります。 /* main.c */ #include <stdio.h> int main(void) { int array[5] = { 0, 1, 2, 3, 4 }; int i; int* p = &array[0]; for( i = 0; i < 5; ++i ){ printf( "%d ", p[i] ); } puts(""); return 0; } /* これをデバッグすると、定義されていないアドレスの配列 p[i] のため、エラーになるような気がしますが、実際には 1 2 3 4 5 と出力されます。 ここで質問ですが、 p[i] とは何を指しているのですか? できればc初心者の中学生でも分かるように教えてください。 p.s. 余計な御世話かもしれませんが、これをこのままコピペすれば、デバッグできます。 */

  • ポインタ定義は必要なんですか?

    #include <stdio.h> int main( void ) { int x; int *p; p = &x; printf("Address = %p\t\n", p ); return 0; } を #include <stdio.h> int main( void ) { int x; int p;←ここを上とはかえた p = &x; printf("Address = %p\t\n", p ); return 0; } にしたところコンパイル時に p = &x に関して 移植性のないポインタ変換と表記されますが 結果は同じだったのでポインタ定義というのは結局必要なんですか? 移植性のないポインタ変換とはなんなんですか? よければ詳しく教えてください

  • ポインタについて

    #include<stdio.h> int main(void){ int i; char *pt = "Hello World"; char a[11]; pt = &a; for(i=0;i<=11;i++){ printf("%c %x\n",pt,&a[i]); pt++; } return(0); } H abcd80(←アドレス) E abcd81(←アドレス) のように表示したいんですが、アドレスだけうまくできてHELLO WORLD のほうがうまく表示できません。 夏休みの間ブランク空けたんでポインタ全て抜けてしまったみたいです^^;  よろしくおねがいします。

  • C 関数とポインタ

    ポインタと関数がよく分かりません。 (日本語がおかしくてすみません(^_^;)) たとえば↓のようなプログラムで、 #include <stdio.h> void increase(int *i); int main(void) { int x = 3; increase(&x); printf("%d\n", x); return 0; } void increase(int *i) { (*i)++; } 結果は4になりますが、increase(&x)が&xとなっていて、 関数はvoid increase(int *i)でint *iになっているのですが、 これはvoid increase(int *i)はint型の「ポインタ」なので、 increase(&x)も&xと「アドレス」を渡さなければいけないということですか?? そして、void increase(int *i)内では、アドレス&xの指す値をインクリメント、という考えで良いのでしょうか?

  • ポインタ参照すると変数が正しく見れない

    なぜdata = &array;がNGなのかがわかりません。 NGの場合、read関数コール前後でdataのアドレスは変更されないようです。 #include <stdio.h> int array = 100; void read( int* data ){   data = &array; // NG   *data = array; // OK } int main(){   int data;   read( &data );   printf(" d : %d\n",data);   return 0; } * 再現環境を簡易化したためこのプログラム自体の有効性はありません

  • ポインタを使って構造体の配列を戻り値にするには

    関数の戻り値を構造体の配列(アドレスを受け渡しを利用して)にしたいのですがうまくゆきません。 以下のプログラムではコンパイルはできるのですが、 a0 = 2 a1 = 4198512 a2 = 4329332 と表示されてしまいa1,a2がうまくゆきません。 ********************************************* #include<stdio.h> struct test{ int a; }; struct test *func(void); void main(void) { struct test *data;//構造体ポインタ int i; data = func(); //ポインタにtest関数の戻り値(アドレス)を代入 for(i=0;i<=2;i++){   printf("a%d = %d\n",i,(data+i)->a); //構造体要素を表示 } } struct test *func(void) { struct test data[3]={1,2,3}; //構造体配列を定義 return (&data[0]); //構造体配列の先頭アドレスを返す } ************************************************* test関数から受ける取ったアドレス(&data[0])をポインタ(data)に代入して1づつずらして表示させれば a0=1,a1=2,a=3 となると思ったのですがどこが間違っているのでしょうか? よろしくお願いします。

  • ポインタによる関数への配列渡し

    林晴比古さんの「新C言語入門」でC言語を勉強している初心者です。 現在ポインタの勉強をしています。色々教科書の文例等をポインタで書くとどうなるか試しております。 上書P200練習問題2に「配列の最大値を返す(その際配列の長さを渡す)」プログラムがあり、それをポインタで渡すプログラムに直してみました。 仮引数に「maxdata」を設定し、そのアドレスを関数側に渡し、関数側ではポインタとして受け取る(そうすれば関数側からはreturnで値を返す必要がない)、と考え、下記のように書いてみました。 #include <stdio.h> void max_of_array(int n[], int len, int *ans); int main(void) { int dt[6] = {50,20,80,30,10,40}; int maxdata; max_of_array(dt,6,&maxdata); printf("最大値=%d\n", maxdata); return 0; } void max_of_array(int n[], int len, int *ans) { int i; ans = &n[0]; for (i=1; i<len; i++){ if (*ans < n[i]) *ans = n[i]; } } しかしコンパイルすると、何故か「最大値=1」となってしまいます。(正しくは80です) 他にも色々試してみましたがうまくいかず、かなり考えてみたのですがどうしても分かりません。お分かりの方、どうすれば正しくなるのが教えてください、よろしくお願いします。

専門家に質問してみよう