45

ポインター記号 * に苦労しています。宣言と式の両方で使用される方法が非常にわかりにくいと思います。

例えば:

int *i; // i is a pointer to an int

しかし、構文の背後にあるロジックは何ですか? i の直前の * はどういう意味ですか? 次の例を見てみましょう。私が間違っているところを修正してください:

char **s;
char *(*s); // added parentheses to highlight precedence

そして、ここで私は道に迷ってしまいます。括弧の間の *s は、次のことを意味します: s はポインターですか? しかし、何へのポインタですか?そして、括弧の外側の * は何を意味するのでしょうか? s が指しているものへのポインターでしょうか?

したがって、これの意味は次のとおりです。sが指しているものを指すポインターは、charへのポインターですか?

私は途方に暮れています。* 記号は、宣言と式で異なって解釈されますか? もしそうなら、それはどのように異なって解釈されますか? どこが間違っていますか?

4

10 に答える 10

82

このようにしてください:

int *ii が指す値が整数であることを意味します。

char **pp は、それ自体が char へのポインターであるポインターであることを意味します。ここに画像の説明を入力

于 2011-03-30T10:06:12.933 に答える
69
int i; //i is an int.
int *i; //i is a pointer to an int
int **i;//i is a pointer to a pointer to an int.

* 記号は、宣言と式で異なって解釈されますか?

はい。それらは完全に異なります。宣言では、* を使用してポインターを宣言します。単項式の * は、ポインターを逆参照するために (または二項乗算演算子として) 使用されます。

いくつかの例:

int i = 10; //i is an int, it has allocated storage to store an int.
int *k; // k is an uninitialized pointer to an int. 
        //It does not store an int, but a pointer to one.
k = &i; // make k point to i. We take the address of i and store it in k
int j = *k; //here we dereference the k pointer to get at the int value it points
            //to. As it points to i, *k will get the value 10 and store it in j
于 2011-03-30T09:50:50.000 に答える
28

c での宣言のルールは、使用する方法で宣言することです。

char *p*p文字を取得する必要があることを意味し、

char **p**p文字を取得する必要があることを意味します。

于 2011-03-30T09:48:37.607 に答える
19

C の宣言は式中心です。つまり、宣言の形式は、実行可能コードの式の形式と一致する必要があります。

たとえば、 という名前の整数へのポインタがあるとしますp。が指す整数値にアクセスしたいので、次のようにポインタp逆参照します。

x = *p; 

のタイプ*pint; したがって、 の宣言は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

式の型が であるため**ppint宣言は

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ます。そのためには、へのポインターを渡す必要がありますffはすでにポインター型 ( ) であるため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
于 2011-03-30T14:35:58.347 に答える
11

複雑な宣言子を解析するための私のお気に入りの方法は、時計回りスパイラル ルールです。

基本的に、識別子から始めて、時計回りのらせんをたどります。それがどのように使用されているかを正確に知るには、リンクを参照してください。

この記事で言及されていない 2 つのこと:

1-型指定子(int、charなど)を宣言子から分離し、宣言子を解析してから型指定子を追加する必要があります。

2- 配列を表す角括弧に遭遇した場合は、次の角括弧 (存在する場合) も必ず読んでください。

于 2011-03-30T09:53:47.823 に答える
6

int * ii が int へのポインターであることを意味します (逆方向に読み取り、* をポインターとして読み取ります)。 どちらも char へのポインターへのポインターを意味しますchar **pchar *(*p)

ここにいくつかの他の例があります

int* a[3]// a は int への 3 つのポインタの配列です

int (*a)[3]//a は 3 つの int の配列へのポインタです

于 2011-03-30T09:44:25.320 に答える
3

あなたの質問に答えがあります。

実際、ポインタからポインタへのポインタを示すために二重星が使用されます。

于 2011-03-30T09:44:05.627 に答える
2

* in 宣言は、変数が他の変数/定数へのポインタであることを意味します。つまり、型の変数のアドレスを保持できます。例: char *c;c は char へのアドレスを保持できることをint *b意味し、b は int のアドレスを保持できることを意味します。参照の型は重要です。ポインター演算でpointer + 1は、実際にはpointer + (1 * sizeof(*pointer)).

* in 式は「アドレスに格納された値」を意味するため、cが文字へのポインタである場合*c、 は特定の文字です。

char *(*s);つまり、s は char へのポインターへのポインターであるため、s は char のアドレスを保持するのではなく、char のアドレスを保持する変数のアドレスを保持します。

于 2011-03-30T09:55:17.117 に答える
1

ここにちょっとした情報があります

         variable    pointer
declaring     &a           p

reading/      a            *p

processing
于 2011-03-30T09:55:51.950 に答える
-1

宣言 &aとは、 を指していることを意味し*iます。結局のところ、それは へのポインタ*intです。整数を指し*iます。しかし、j = *kがポインター this へのポインターで&kある場合、 は の値になり、kへのkポインターを持つことを意味し*intます。

于 2016-01-14T07:32:48.067 に答える