解释声明

C 的独特语法特性是声明镜像使用声明的对象,就像它在普通表达式中一样。

具有相同优先级和关联性的以下运算符集在声明符中重用,即:

  • 一元 * dereference 运算符,表示指针;
  • 二进制 [] 数组索引运算符,表示一个数组;
  • (1 + n)-ary ()函数调用运算符表示函数;
  • () 分组括号,它覆盖其余列出的运算符的优先级和相关性。

以上三个运算符具有以下优先级和关联性:

操作者 相对偏好 关联性
[](阵列顺序) 1 左到右
()(函数调用) 1 左到右
*(取消引用) 2 右到左

在解释声明时,必须从标识符向外开始,并按照上表以正确的顺序应用相邻的运算符。运算符的每个应用程序都可以用以下英文单词代替:

表达 解释
thing[X] 一系列大小的 X of …
thing(t1, t2, t3) 一个功能采取 t1t2t3 并返回…
*thing 一个指向…的指针

因此,英语解释的开头将始终以标识符开头,并以声明左侧的类型结束。

例子

char *names[20];

[] 优先于*,所以解释是:names 是一个指向 char 的指针大小为 20 的指针数组。

char (*place)[10];

如果使用括号覆盖优先级,则首先应用*place 是指向 char 的 10 号数据的指针。

int fn(long, short);

这里没有优先担心:fn 是一个采用 longshort 参数和返回 int 的函数。

int *fn(void);

首先应用 ()fn 是一个采用 void 并返回指向 int 的函数。

int (*fp)(void);

覆盖 () 的优先级:fp 是指向 void 并返回 int 的函数的指针。

int arr[5][8];

多维数组不是规则的例外; [] 运算符根据表中的关联性以从左到右的顺序应用:arr 是一个大小为 5 的数组,大小为 8 的 int

int **ptr;

两个解除引用运算符具有相同的优先级,因此关联性生效。运算符按从右到左的顺序应用:ptr 是指向 int 的指针。

多个声明

逗号可以用作分隔符 ,,以便在单个语句中分隔多个声明。以下语句包含五个声明:

int fn(void), *ptr, (*fp)(int), arr[10][20], num;

上例中声明的对象是:

  • fn:采取 void 并返回 int 的功能;
  • ptr:指向 int 的指针;
  • fp:指向 int 并返回 int 的函数的指针;
  • arr:一个大小为 10 的数组,大小为 20;
  • numint

替代解释

因为声明镜像使用,所以声明也可以根据可以应用于对象的运算符和该表达式的最终结果类型来解释。位于左侧的类型是应用所有运算符后产生的最终结果。

/*
 * Subscripting "arr" and dereferencing it yields a "char" result.
 * Particularly: *arr[5] is of type "char".
 */
char *arr[20];

/*
 * Calling "fn" yields an "int" result.
 * Particularly: fn('b') is of type "int".
 */
int fn(char);

/*
 * Dereferencing "fp" and then calling it yields an "int" result.
 * Particularly: (*fp)() is of type "int".
 */
int (*fp)(void);

/*
 * Subscripting "strings" twice and dereferencing it yields a "char" result.
 * Particularly: *strings[5][15] is of type "char"
 */
char *strings[10][20];