考虑以下代码(它是 this discussion 的结果):
#include <stdio.h>
void foo(int (*p)[]) { // Argument has incomplete array type
printf("%d\n", (*p)[1]);
printf("%d\n", p[0][1]); // Line 5
}
int main(void) {
int a[] = { 5, 6, 7 };
foo(&a); // Line 10
}
海湾合作委员会 4.3.4 complains错误信息:
prog.c: In function ‘foo’:
prog.c:5: error: invalid use of array with unspecified bounds
GCC 4.1.2 中的相同错误消息,并且似乎是 -std=c99
、-Wall
、-Wextra
的不变量。
所以它对表达式 p[0]
不满意,但它对 *p
很满意,即使它们(理论上)应该是等价的。如果我注释掉第 5 行,代码将编译并执行我“预期”的操作(显示 6
)。
推测以下情况之一为真:
- 我对 C 标准的理解不正确,这些表达式不是等价的。
- GCC 有一个错误。
我会把钱放在 (1) 上。
问题:任何人都可以详细说明这种行为吗?
说明:我知道这可以通过在函数定义中指定数组大小来“解决”。这不是我感兴趣的。
对于“奖励”点:当 MSVC 2010 拒绝第 10 行并显示以下消息时,任何人都可以确认 MSVC 2010 是错误的吗?
1><snip>\prog.c(10): warning C4048: different array subscripts : 'int (*)[]' and 'int (*)[3]'
最佳答案
n1570 的第 6.5.2.1 节,数组下标:
Constraints
One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.
因此,如果 p
是指向不完整类型的指针,则标准禁止表达式 p[0]
。对于间接运算符*
则没有这样的限制。
然而,在旧版本/标准草案(n1256 和 C99)中,该段中没有“完整”一词。没有以任何方式参与标准程序,我只能猜测这是一个重大变化还是对遗漏的更正。编译器的行为表明后者。 p[i]
符合与 *(p + i)
相同的标准,并且后一个表达式对于指向的指针没有意义一个不完整的类型,所以如果 p
是一个指向不完整类型的指针,那么要让 p[0]
工作,就需要一个显式的特殊情况。
关于c - 不完整数组类型的 p[0] 和 *p 等价,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10183943/