<構造体へのポインタ>
構造体の変数も配列も、通常の変数や配列と同じようにメモリを割り当てられており、そのアドレスも同じように参照することができます。また、そのアドレスも「構造体へのポインタ」に格納することができます。ポインタのインクリメントなどの演算も通常のポインタと同様です。
struct sample s1, s2[10], *sp1,
*sp2;
...
sp1 = &s1; // sp1にs1のアドレスを代入
sp2 = s2; // sp2に配列s2の先頭アドレスを代入
sp2++; // sp2をインクリメント(s2[1]を指す)
ポインタが指している構造体のメンバにアクセスするには、例えば
(*sp2).no = 1;
のように書くこともできますが、通常はピリオドの代わりにアロー演算子"->"を使って、
sp2->no = 1;
のように書くのが一般的です。
(sp2+1)->no = 2;
といった書き方もできます。
<関数との構造体のやり取り>
もちろん、構造体を引数として関数に渡したり、関数から構造体を返却値として返したりすることもできます。下は、構造体の値渡しの例です。
typedef struct large_data {
char
name[20];
double
buf[100];
} DATA;
DATA sort_data(DATA dat);
しかし、しばしば構造体は一つ一つが大きなオブジェクトになるので、このような関数とのやり取りは、処理上のオーバーヘッドを増すことになります。
従って、関数との構造体のやり取りには、構造体へのポインタを使うのが普通です。
DATA *sort_data(DATA *dat);
ポインタの内容(構造体のアドレス)を伝えることで、呼び出し元と関数側で同じ構造体の中身を共有することができるわけです。