如何理解C中的指针星*?

我正在努力使用指针符号*,我发现它在声明和表达式中的使用方式非常混乱。

例如:

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

但是语法背后的逻辑是什么? *之前的*是什么意思? 我们来看下面的例子。 请纠正我错在哪里:

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

这就是我失去轨道的地方。 parantheses之间的* s意味着:s是指针? 但指针是什么? 括号外的*是什么意思:指向s指向的指针?

所以这个意思是:指向s指向的指针是一个指向char的指针?

我很茫然。 *符号在声明和表达式中的解释是否不同? 如果是这样,它的解释方式有何不同? 我哪里错了?

c中的声明规则是,你以你使用它的方式声明它。

char *p表示你需要*p来获取char,

char **p意味着你需要**p来获取char。

这样吧:

int *i表示i指向的值是整数。

char **p表示p是一个指针,它本身就是一个指向char的指针。 在此处输入图像描述

 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 

C语句中的声明是以表达式为中心的,这意味着声明的forms应该与可执行代码中表达式的forms相匹配。

例如,假设我们有一个指向名为p的整数的指针。 我们想要访问p指向的整数值,所以我们取消引用指针,如下所示:

 x = *p; 

表达式 *p的类型是int ; 因此, p的声明采取forms

 int *p; 

在此声明中, int类型说明符*p声明 。 声明器引入了声明对象的名称( p ),以及类型说明符未提供的其他类型信息。 在这种情况下,附加类型信息是p是指针类型。 声明可以读作“ p是指向int的类型指针”或“ p是指向int类型的指针”。 我更喜欢使用第二种forms,其他人更喜欢第一种forms。

这是C和C ++语法的意外,您可以将该声明写为int *p;int* p; 。 在这两种情况下,它都被解析为int (*p); – 换句话说, *始终与变量名称相关联,而不是类型说明符。

现在假设我们有一个指向int的指针数组,我们想要访问数组的第i个元素指向的值。 我们下标到数组并取消引用结果,如下所示:

 x = *ap[i]; // parsed as *(ap[i]), since subscript has higher precedence // than dereference. 

同样, 表达式 *ap[i]int ,因此ap的声明是

 int *ap[N]; 

其中声明*ap[N]表示ap是指向int的指针数组。

并且只是为了将点驱动回家,现在假设我们有一个指向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 * ),这意味着我们将指针传递给FILE * ,因此p的声明为FILE **p 。 请记住, openAndInit中的表达式 *p指的是与main中的表达式f相同的对象。

在声明和表达式中, []()都优先于一元* 。 例如, *ap[i]被解释为*(ap[i]) ; 表达式ap[i]是指针类型, *取消引用该指针。 因此ap是一个指针数组 。 如果要声明指向数组指针 ,则必须使用数组名称显式分组* ,如下所示:

 int (*pa)[N]; // pa is a pointer to an N-element array of int 

当您想要访问数组中的值时,您必须在应用下标之前使用deference pa

 x = (*pa)[i]; 

与function类似:

 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 

我最喜欢的解析复杂声明符的方法是顺时针螺旋规则 。

基本上你从标识符开始并遵循顺时针螺旋。 请参阅链接以了解其使用方式。

文章没有提到两件事:

1-您应该将类​​型说明符(int,char等)与声明符分开,解析声明符,然后添加类型说明符。

2-如果遇到表示数组的方括号,请务必阅读以下方括号(如果有)。

int * i表示i是指向int的指针(向后读,读*作为指针)。 char **pchar *(*p)都表示指向char的指针。

这是其他一些例子

int* a[3] // a是一个由3个指向int的数组

int (*a)[3] // a是指向3个int的数组的指针

你的问题有答案。

实际上,双星用于指示指针的指针。

声明中的*表示变量是指向其他变量/常量的指针。 意思是它可以保存类型变量的地址。 例如: char *c; 表示c可以将地址保存到某个char,而int *b表示b可以保存某些int的地址,引用的类型很重要,因为在指针算术中, pointer + 1实际上是pointer + (1 * sizeof(*pointer))

表达式中的*表示“存储在地址中的值”,因此如果c是指向某个char的指针,则*c是特定的char。

char *(*s); 这意味着s是指向char的指针,因此s不保存char的地址,而是保存char的地址的变量的地址。

这里有一些信息

  variable pointer declaring &a p reading/ a *p processing 

声明&a它指向*i &a手段。 毕竟它是一个指向*int的指针。 整数是指向*i 。 但是如果考虑j = *k是指向this的指针,则表示&k将是&k的值, k将具有指向*int指针。