如何解读C语言中复杂的指针声明?

9
所以我想举一个例子:
int *pi; // pi is a pointer that points to an integer
const int *cpi; // cpi is a pointer that points to a constant integer
char *pc; // pc is a pointer to a char 

我该如何读取这些内容:
char **x; //x is a pointer to a char pointer?
char *y[];
char **z[];

谢谢。

7
cdecl.org是一个在线C语言声明解析器,可以帮助您理解复杂的C语言声明。 - Bill Lynch
@BillLynch 我认为这并不完全正确。应该是char *titles[]等于char **titles;吧? - Koray Tugay
3
在 C 语言中,数组名即是指向该数组首元素的指针。因此,可以使用数组名作为指针来访问数组元素,也可以对其进行指针运算。 - Bill Lynch
@BillLynch 那又怎样? - Koray Tugay
1
@BillLynch:这取决于它的位置。在函数参数列表中,T * t[] 等同于 T ** t - alk
显示剩余5条评论
4个回答

15

cdecl.org常常与这样的问题联系在一起。毫无疑问,它使得解密任何复杂声明更容易,但同时它仅提供一个抽象的信息。作为一名C或C++程序员,应该知道如何手动解密复杂的声明。 螺旋规则在某种程度上有所帮助,但在某些情况下失败了。这个答案将帮助程序员手动解密任何复杂声明。


记住这两个简单的规则:

  1. 始终从内向外阅读声明。
  2. 如果有选择,始终优先使用[]()而不是*

第一条规则简单地表示,找到正在声明的变量,并从它开始解密声明。

对于第二条规则,如果*位于标识符之前,后面跟着[](),则该标识符表示一个数组或函数(分别),而不是指针。

示例1:

char *y[5]; 
  • 变量/标识符为y
  • *[]之后,紧跟着y
  • y必须是一个数组。

将上述解密组合起来得到:y是一个指向char的5个指针的数组

请注意,您可以始终使用括号来覆盖[]()的正常优先级。

示例2:

void (*pf) (int);
  • 变量/标识符是pf
  • *pf被括号括起来,必须是一个指针。
  • ()跟在*pf后面,表示pf必须指向一个函数。
  • 由于()包含int,因此该函数必须期望一个类型为int的参数。

因此,pf是一个指向期望一个int参数并返回值为空的函数的指针

现在,请解密以下声明后会得到什么结果:

TBD
int *(*a[5])(void);  

答案:

a 是指向不带参数且返回指向 int 的函数指针数组。


注: 请注意,两个

标签中间可能存在其他未提供的内容。

char *y[];
char **z[];  

如果它们不作为函数的参数声明,就会导致编译错误。如果它们是函数的参数,则 char *y[] 等同于 char **ychar **z[] 等同于 char ***z
如果不是这种情况,则需要像我在第一个示例中所做的那样指定维度。


5

以下是一些示例C声明,取自HELPPC实用程序(作者David Jurgens),它在90年代曾经拯救了我的(编程)生命(该实用程序的在线版本在此处:http://stanislavs.org/helppc

int i;                  i as an int
int *i;                 i as a pointer to an int
int **i;                i is a pointer to a pointer to an int
int *(*i)();            i is a pointer to a function returning a
                          pointer to int
int *(*i[])();          i is an array of pointers to functions
                          returning pointers to an int
int *i[5];              i is an array of 5 pointers to int
int (*i)[5];            i is a pointer to an array of 5 ints
int *i();               i is a function returning a pointer to an int
int (*i)();             i is a pointer to a function returning int
int *(*(*i)())[5]       i is a pointer to a function returning a
                          pointer to an array of 5 pointers to an int

0

y 是指向字符指针的数组,z 是指向指向字符指针的指针的数组。 x 是指向指向字符指针的指针的指针。


你为什么认为y是一个指向char的指针数组?对我来说,y看起来不像是一个数组。 - haccks

0
char **x; //x is a pointer to a pointer to char
char *y[]; // y is an array of pointers to char
char **z[]; // z is an array of pointers to pointers to char

通常,阅读这样的表达式最简单的方法是从右端开始,一直读到左端。 - user3629249
1
@KorayTugay,'x'的定义并没有表明会有多个字符,也没有表明多个字符将以NUL字节终止。但是上下文可能表明这是正确的。 - user3629249
1
y不是char指针数组。它会导致编译错误。对于z也是一样。 - haccks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接