解释复杂声明符
可以将任何声明符括在圆括号中以指定“复杂声明符”的特殊解释。复杂声明符是由多个数组、指针或函数修饰符限定的标识符。 您可以将数组、指针和函数修饰符的各种组合应用于单个标识符。 通常 typedef
可用来简化声明。 请参阅 Typedef 声明。
在解释复杂声明符时,方括号和圆括号(即,标识符右侧的修饰符)优先于星号(即,标识符左侧的修饰符)。 方括号和圆括号具有相同的优先级并且都是从左到右关联。 在完全解释声明符之后,将应用类型说明符以作为最后一步。 通过使用圆括号,您可以重写默认关联顺序和强制实施特定解释。 但是,绝不要单独在标识符名称两边使用圆括号。 这可能会被错误解释为参数列表。
解释复杂声明符的一个简单方法是通过下列 4 个步骤“从里到外”地读取它们:
从标识符开始并直接查找方括号或圆括号(如果有)的右侧。
解释这些方括号或圆括号,然后查找星号的左侧。
如果在任何阶段遇到一个右圆括号,请返回并将规则 1 和 2 应用于圆括号内的所有内容。
应用类型说明符。
char *( *(*var)() )[10]; ^ ^ ^ ^ ^ ^ ^ 7 6 4 2 1 3 5
在此示例中,步骤是按顺序编号的,并且可以按如下方式解释:
标识符
var
声明为指向以下内容的指针
返回以下内容的函数
指向以下内容的指针
包含 10 个元素的数组,这些元素分别为
指向以下内容的指针
char
值。
示例
以下示例阐释了其他复杂声明并演示了圆括号如何影响声明的含义。
int *var[5]; /* Array of pointers to int values */
数组修饰符的优先级高于指针修饰符,因此,var
将声明为数组。 指针修饰符将应用于数组元素的类型;因此,数组元素是指向 int
值的指针。
int (*var)[5]; /* Pointer to array of int values */
在对 var
的此声明中,圆括号为指针修饰符赋予了高于数组修饰符的优先级,并且 var
被声明为指向包含 5 个 int
值的数组的指针。
long *var( long, long ); /* Function returning pointer to long */
函数修饰符的优先级也高于指针修饰符,因此对 var
的此声明将 var
声明为返回指向 long
值的指针的函数。 此函数被声明为接受两个 long
值作为参数。
long (*var)( long, long ); /* Pointer to function returning long */
此示例与前一个示例类似。 括号赋予指针修饰符比函数修饰符更高的优先级,并且 var
被声明为指向返回 long
值的函数的指针。 同样,此函数接受两个 long
参数。
struct both /* Array of pointers to functions */
{ /* returning structures */
int a;
char b;
} ( *var[5] )( struct both, struct both );
数组的元素不能是函数,但此声明演示了如何将指针数组声明为函数。 在此示例中,var
被声明为包含 5 个指向函数(返回具有两个成员的结构)的指针的数组。 函数的参数被声明为具有同一结构类型 both
的两个结构。 请注意,*var[5]
两边需要圆括号。 如果没有它们,声明将是对声明函数数组的非法尝试,如下所示:
/* ILLEGAL */
struct both *var[5](struct both, struct both);
以下语句声明指针的数组。
unsigned int *(* const *name[5][10] ) ( void );
name
数组具有组织在一个多维数组中的 50 个元素。 这些元素是指向常量指针的指针。 此常量指针指向没有参数并返回指向无符号类型的指针的函数。
下一个示例是函数,此函数返回指向包含三个 double
值的数组的指针。
double ( *var( double (*)[3] ) )[3];
在此声明中,函数将返回指向数组的指针,因为返回数组的函数是非法的。 在此处,var
被声明为函数,此函数返回指向包含三个 double
值的数组的指针。 函数 var
将采用一个参数。 与返回值一样,此参数是指向包含三个 double
值的数组的指针。 参数类型由一个复杂 abstract-declarator 给定。 参数类型中星号两边的括号是必需的;如果没有括号,参数类型就是包含三个指向 double
值的指针的数组。 有关抽象声明符的讨论和示例,请参阅抽象声明符。
union sign /* Array of arrays of pointers */
{ /* to pointers to unions */
int x;
unsigned y;
} **var[5][5];
如上面的示例所示,指针可以指向另一个指针,数组可包含数组作为元素。 这里的 var
是一个包含五个元素的数组。 每个元素都是一个五元素指针数组,这些指针指向指向具有两个成员的联合的指针。
union sign *(*var[5])[5]; /* Array of pointers to arrays
of pointers to unions */
此示例演示圆括号的放置如何更改声明的含义。 在此示例中,var
是一个五元素指针数组,这些指针指向联合的五元素指针数组。 有关如何使用 typedef
避免复杂声明的示例,请参阅 Typedef 声明。