構造体も当然メモリ上に領域を確保します。ということは、ポインタで操作することが出来るはずです。(この章では配列での例を示しますが、そうでない場合も同じです。)
/*01*/ #include <stdio.h>
/*02*/
/*03*/ struct score{
/*04*/ char name[16];
/*05*/ int math;
/*06*/ int english;
/*07*/ int kei;
/*08*/ };
/*09*/
/*10*/ main()
/*11*/ {
/*12*/ struct score a[5];
/*13*/ struct score *p;
/*14*/ int i;
/*15*/
/*16*/ p = a;
/*17*/ printf("名前 英語の点 数学の点 を入力してください。\n");
/*18*/ for(i = 0; i < 5; i++){
/*19*/ scanf("%s%d%d", p->name, &p->math, &p->english);
/*20*/ p->kei = p->math + p->english;
/*21*/ p++;
/*22*/ }
/*23*/
/*24*/ p = a;
/*25*/ putchar('\n');
/*26*/ for(i = 0; i < 5; i++){
/*27*/ printf("%s の合計点は %d です。\n", p->name, p->kei);
/*28*/ p++;
/*29*/ }
/*30*/
/*31*/ return 0;
/*32*/ }
この例で作られた struct score 型変数 a[5] は.のようにメモリ上へ作られます。
構造体変数のアドレスを求める方法も普通の変数と同じで「&」を使います。また、構造体変数のアドレスを求めた場合、普通の変数のときと同様、それぞれの最初のアドレスになります。ですから、上の図の例では「&a[0]」とすると「300」が、「&a[1]」とすると「328」が求まるわけです。
構造体ポインタ変数を宣言しています。この例では struct score 型のポインタを宣言しています。これで p には struct score 型のアドレスを入れることができます。では p に a[0] のアドレスを入れてみましょう。
p = &a[0];
これまでの知識から考えると、構造体変数の中身をポインタで操作する場合、「(*p).kei」などとなりそうですね。これも正しいです(演算順位の関係によりカッコは必要)。ですが、構造体変数をポインタで操作するということはよく行なう手法なので、もっと簡単に扱う方法があります。それが「p->kei」という矢印のような書き方です(マイナス記号と比較演算子:これを
(*ポインタ).メンバ ポインタ->メンバ /*2つとも同じ*/ 例: (*p).kei p->kei
また、scanf ではアドレスが必要なので「&」を付けて、「&(p->kei)」のように書きますが、演算順位によりカッコをはずして「&p->kei」とかくことができます。name メンバの時だけ「&」記号が無いのは前章と同様 name が配列だからです(配列名だけだと、その先頭アドレスを指すのでした)。
&(p->kei) &p->kei &((*p).kei) &(*p).kei /*これらはいずれも同じです。*/
普通の変数のポインタ操作と同じで、インクリメントなどが行えます。最初に p が a[0] を指していたとすれば、p をインクリメントすることによって a[1] を指すようにします。