如何理解C中的指针星*?
Posted
技术标签:
【中文标题】如何理解C中的指针星*?【英文标题】:How to understand the pointer star * in C? 【发布时间】:2011-07-25 23:19:50 【问题描述】:我正在为指针符号 * 苦苦挣扎,我发现它在声明和表达式中的使用方式非常令人困惑。
例如:
int *i; // i is a pointer to an int
但是语法背后的逻辑是什么? i 前面的 * 是什么意思?让我们看下面的例子。请纠正我的错误:
char **s;
char *(*s); // added parentheses to highlight precedence
这就是我迷路的地方。括号之间的 *s 表示:s 是指针?但是指向什么的指针?括号外的 * 是什么意思:指向 s 的指针?
所以这里的意思是:指向s所指向的指针是指向一个char的指针吗?
我很茫然。 * 符号在声明和表达式中的解释是否不同?如果是这样,它如何解释不同?我哪里错了?
【问题讨论】:
【参考方案1】:声明&a
表示它指向*i
。毕竟它是一个指向*int
的指针。一个整数指向*i
。但如果考虑j = *k
是指向指针this 的指针,则意味着&k
将是k
的值,而k
将具有指向*int
的指针。
【讨论】:
【参考方案2】:c 中的声明规则是,你以你使用它的方式声明它。
char *p
表示您需要*p
来获取字符,
char **p
表示您需要**p
才能获取字符。
【讨论】:
【参考方案3】:C 中的声明以表达式为中心,这意味着声明的形式应与可执行代码中的表达式形式相匹配。
例如,假设我们有一个指向名为p
的整数的指针。我们要访问p
指向的整数值,所以我们取消引用指针,如下所示:
x = *p;
表达式的类型*p
是int
;因此,p
的声明采用以下形式
int *p;
在此声明中,int
是类型说明符,*p
是声明符。声明器引入了被声明对象的名称 (p
),以及类型说明符未提供的其他类型信息。在这种情况下,附加的类型信息是p
是一个指针类型。声明可以读作“p
是指向int
的类型指针”或“p
是指向int
类型的指针”。我更喜欢使用第二种形式,其他人更喜欢第一种。
您可以将声明编写为int *p;
或int* p;
,这是C 和C++ 语法的一个意外。在这两种情况下,它都被解析为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
当你想访问数组中的一个值时,你必须在应用下标之前遵从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
【讨论】:
【参考方案4】: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
【讨论】:
【参考方案5】:这样说:
int *i
表示i指向的值是一个整数。
char **p
表示 p 是一个指针,它本身就是一个指向 char 的指针。
【讨论】:
【参考方案6】:这里有一些信息
variable pointer
declaring &a p
reading/ a *p
processing
【讨论】:
【参考方案7】:声明中的 * 表示该变量是指向其他变量/常量的指针。意味着它可以保存该类型变量的地址。例如:char *c;
表示c可以保存某个char的地址,而int *b
表示b可以保存某个int的地址,引用的类型很重要,因为在指针算术中,pointer + 1
实际上是@ 987654324@.
表达式中的 * 表示“存储在地址中的值”,因此如果 c
是指向某个字符的指针,则 *c
是特定字符。
char *(*s);
表示s是一个指向char的指针,所以s不保存char的地址,而是保存char地址的变量的地址。
【讨论】:
【参考方案8】:我最喜欢的解析复杂声明符的方法是clockwise-spiral rule。
基本上,您从标识符开始并遵循顺时针螺旋。请参阅链接以了解其具体使用方法。
文章没有提到的两件事:
1- 应该将类型说明符(int、char 等)与声明符分开,解析声明符,然后添加类型说明符。
2- 如果遇到表示数组的方括号,请务必阅读以下方括号(如果有的话)。
【讨论】:
你能给你的1和2举个例子吗?有读数?会很好的补充 请注意,如果您想“顺时针”调用该规则,您还必须记住从名称向上走,否则您会得到不正确的结果。【参考方案9】:int * i
表示 i 是指向 int 的指针(向后读取,将 * 读取为指针)。
char **p
和 char *(*p)
都表示指向 char 指针的指针。
这里有一些其他的例子
int* a[3]
// a 是一个包含 3 个指向 int 的指针的数组
int (*a)[3]
//a 是一个指向 3 个整数数组的指针
【讨论】:
【参考方案10】:你的问题有答案。
确实用双星来表示指向指针的指针。
【讨论】:
以上是关于如何理解C中的指针星*?的主要内容,如果未能解决你的问题,请参考以下文章