char *p配列は要素型のオブジェクトが連続してメモリに記憶されるデータであり,配列型は式で使うと第1要素のアドレスに変換され,そのアドレスのメモリ箇所に入っている値に直接アクセスできる方法(間接参照)があることも見ました。ポインタ型データ,すなわち,アドレスについて理解したことでしょう。ここでは,ポインタ型データを扱うための変数,「ポインタ」の導入方法を見ます。
ポインタを導入するためには,宣言子にポインタ宣言子を用います。
■ポインタ宣言子(Pointer Declarator)
*識別子
T *識別子 = 初期化子;
と宣言しなければなりません。この宣言よって得られる変数 識別子 がT へのポインタ型データに対するポインタです。型は「T へのポインタ」であり,それは
T *
となります。初期化子には,T へのポインタ型データを代入します。
/* Example 10.5 */
#include <stdio.h>
int main(void)
{
char str[] = "ABCDEFG";
char *p = str;
printf("str[0] = '%c' [%p]\n", *p, p);
return 0;
}
これは Example 10.3 をポインタ p を用いて書き直したものです。ポインタ p は char *型,すなわち,charへのポインタ型です。str は配列の第1要素を指し示す char へのポインタです。したがって,ポインタ p は str に初期化されることになります。すなわち,宣言
char *p = str;
は,char * 部分が型,p = str 部分が初期化であり,したがって,char *型変数の初期化になります。
一方,printf関数
printf("'%c' [%p]\n", *p, p);
の中の *p は p の間接参照です。すなわち,*p の * は間接演算子です。また,p = str なので,printf関数内の p は str の値となります。
かくして,実行結果は,
str[0] = 'A' [0xbffffa18]
となり,Example 10.3 の結果と同じになります。(但し,機械によってはアドレスは異なるかもしれません。)