->構造体メンバを参照する演算子には既に見た「メンバ演算子」と,もう一つ「ポインタ演算子」があります。ここでは「ポインタ演算子」を見ます。
ポインタ演算子は,構造体へのポインタよりメンバを参照するものです。次の宣言
struct s {
       int n;
       char str[12];
} x[20], *p;
におけるオブジェクト x は構造体 s 型配列,そして p は構造体 s 型へのポインタです。これに対し,式文
p = x;
が実行されると,ポインタ p に配列 x[20] の第1要素のアドレスが代入されます。(配列型の文法を参照。)間接参照すると *p = x[0] ですが,操作対象の値は x[0] ではなく,そのメンバ x[0].n や x[0].str です。したがって,間接演算子を使った値の参照ができません。そこで,ポインタからメンバを直接参照できる仕組みが必要です。それが「ポインタ演算子」です。
■ポインタ演算子(Pointer Operator)
ポインタ -> メンバ名
例えば,上のケースを使えば,p -> n == x[0].n が成り立ちます。したがって,
p -> n = 4;
とすれば,x[0].n に 4 が代入されます。すなわち,式文
x[0].n = 4;
を実行したことと同じことになります。一般的には,構造体変数 x とメンバ m,そしてポインタ p == &x があったとき,
p -> m == x.m
が成り立つことになります。
/* Example 11.11 */
#include <stdio.h>
#include <string.h>
struct s {
       char n;
       char str[12];
} x[20] = {
       {1, "first"},
       {2, "second"},
       {3, "third"}
};
int main(void)
{
       struct s *p;
       for (p = x; p -> n != 0; p++)
              printf("x[%td] %d %s\n", p - x, p -> n, p -> str);
       p -> n = 4;
       memcpy(p -> str, "fourth", sizeof(p -> str) - 1);
       printf("x[%td] %d %s\n", p - x, p -> n, p -> str);
       return 0;
}
この例の for文は「配列の末尾を探す」の構造体配列版です。繰り返しの条件 p -> n != 0 は,ポインタ p が現在指しているアドレス(配列 x[i] のアドレス)のメンバ n の値が 0 でなければという意味です。また printf内の p - x は「ポインタ同士の差」です。実行すると,次のように出力されます。
x[0] 1 first x[1] 2 second x[2] 3 third x[3] 4 fourth
x[3] に指定した値や文字列が代入されています。