以下是基本规则:
对于任何1类型T,您可以有以下任何一种:
T *p; // p is a pointer to T
T *a[N]; // a is an array of pointer to T
T (*a)[N]; // a is a pointer to an array of T
T *f(); // f is a function returning pointer to T
T (*f)(); // f is a pointer to a function returning T
后缀 [] 和 () 运算符的优先级高于一元 *,因此像 *p[i] 这样的表达式被解析为 *(p[i])。如果要索引p 指向 的内容,则需要将* 运算符与p 或(*p)[i] 显式分组。此优先规则适用于表达式和声明。
除非它是sizeof、_Alignof 或一元& 运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,表达式 “T”类型的“N 元素数组”将被转换(“衰减”)为“指向T”的指针类型的表达式,表达式的值将是数组第一个元素的地址。所以给出声明
int a[4] = {10, 20, 30, 40};
以下都是正确的:
Expression Type Decays to Equivalent value
---------- ---- --------- ----------------
a int [4] int * &a[0]
&a int (*)[4] n/a &a[0]
*a int n/a a[0]
表达式a 的类型为“int 的四元素数组”(int [4])。 a 不是sizeof、_Alignof 或一元& 运算符的操作数,因此表达式“衰减”为“指向int”的指针,表达式的值是第一个元素。这个表达式的结果完全等同于&a[0]。
表达式&a 的类型为“指向int 的4 元素数组的指针”(int (*)[4])。在这种情况下,a 是一元 & 运算符的操作数,因此不适用衰减规则。
所有表达式a、&a 和&a[0] 产生相同的值(a 的第一个元素的地址),但类型 的表达式是不同的(这可能会影响值的表示方式)。 a 和&a[0] 的类型是int *,但&a 的类型是int (*)[4]。
类型对于指针运算之类的事情很重要。假设以下声明:
int a[4] = {0, 1, 2, 3};
int *p = a;
int (*ap)[4] = &a;
p 和 ap 最初都指向同一个地址。但是,表达式 p + 1 将在 p 指向的任何对象(IOW,&a[1])之后产生下一个 int 对象的地址,而 ap + 1 将产生int 的下一个 4 元素数组 在 a 之后。
这正是数组下标的工作原理 - 表达式 a[i] 被评估为 *(a + i)。给定起始地址a,偏移i 对象(不是字节)并取消引用结果。
这就是您在某些作业中遇到错误的原因 - int * 和 int (*)[4] 类型不兼容。一方面,它们不必以相同的方式表示(尽管在您可能使用的任何系统上它们都将是),并且在使用指针算术时它们的行为不同。
指向不同类型的指针本身就是不同的类型,通常不能互换。
- 嗯,几乎所有的 - 函数都不能返回数组或函数类型,而且你不能有函数类型的数组,所以对于
T (*a)[N]T不能是函数类型,对于@987654380 @T 不能是函数或数组类型。