C の宣言は式中心です。つまり、宣言の形式は、実行可能コードの式の形式と一致する必要があります。
たとえば、 という名前の整数へのポインタがあるとしますp。が指す整数値にアクセスしたいので、次のようにポインタpを逆参照します。
x = *p;
式 のタイプ*pはint; したがって、 の宣言はp次の形式を取ります
int *p;
この宣言でintは、 は型指定子、*pは宣言子です。p宣言子は、型指定子によって提供されない追加の型情報と共に、宣言されるオブジェクトの名前 ( ) を導入します。この場合、追加の型情報はpポインタ型です。p宣言は、" is of type pointer to int" または " pis a pointer to type "として読み取ることができますint。私は 2 番目の形式を使用することを好みますが、最初の形式を好む人もいます。
int *p;その宣言をまたはのいずれかとして記述できるのは、C および C++ 構文の偶然ですint* p;。どちらの場合も、次のように解析されます。int (*p);つまり、*は型指定子ではなく、常に変数名に関連付けられます。
へのポインターの配列があり、配列intの i 番目の要素が指す値にアクセスしたいとします。次のように、配列に添字を付けて結果を逆参照します。
x = *ap[i]; // parsed as *(ap[i]), since subscript has higher precedence
// than dereference.
繰り返しますが、式の型はis *ap[i]なのでint、 の宣言はapis
int *ap[N];
ここで、宣言子は、 へのポインターの配列である*ap[N]ことを示します。 apint
ポイントを理解するために、ポインターへのポインターがintあり、その値にアクセスしたいとします。繰り返しますが、ポインターを参照し、次にその結果を逆参照して整数値を取得します。
x = **pp; // *pp deferences pp, then **pp dereferences the result of *pp
式の型が であるため**pp、int宣言は
int **pp;
宣言子**ppは、ppが への別のポインターへのポインターであることを示しますint。
通常、次のように、関数に渡すポインター値を変更する場合に、二重間接参照が多く発生します。
void openAndInit(FILE **p)
{
*p = fopen("AFile.txt", "r");
// do other stuff
}
int main(void)
{
FILE *f = NULL;
...
openAndInit(&f);
...
}
この場合、関数で の値を更新する必要がありfます。そのためには、へのポインターを渡す必要がありますf。fはすでにポインター型 ( ) であるためFILE *、ポインターを a に渡していることを意味します。したがって、 as をFILE *宣言します。inの式は inの式と同じオブジェクトを参照することに注意してください。 pFILE **p *popenAndInitfmain
宣言と式の両方[]で、 との両方()が unary よりも優先され*ます。たとえば、次のように*ap[i]解釈され*(ap[i])ます。式ap[i]はポインター型であり、*そのポインターを逆参照します。したがって、ポインタapの配列です。array へのポインタを宣言する場合は、次のように明示的に配列名でグループ化する必要があります。*
int (*pa)[N]; // pa is a pointer to an N-element array of int
また、配列内の値にアクセスする場合はpa、添え字を適用する前に参照する必要があります。
x = (*pa)[i];
関数についても同様です。
int *f(); // f is a function that returns a pointer to int
...
x = *f(); // we must dereference the result of f() to get the int value
int (*f)(); // f is a pointer to a function that returns an int
...
x = (*f)(); // we must dereference f and execute the result to get the int value