Oli*_*rth 19 c arrays gcc pointers incomplete-type
考虑以下代码(它是由于此讨论而产生的):
#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
}
Run Code Online (Sandbox Code Playgroud)
GCC 4.3.4 抱怨错误消息:
prog.c: In function ‘foo’:
prog.c:5: error: invalid use of array with unspecified bounds
Run Code Online (Sandbox Code Playgroud)
在GCC 4.1.2相同的错误消息,并且似乎是不变的-std=c99,-Wall,-Wextra.
所以它对表达式不满意p[0],但它很满意*p,尽管这些(理论上)应该是等价的.如果我注释掉第5行,代码会编译并执行我"期望"(显示6)的内容.
大概有以下之一是真的:
我把钱放在(1)上.
问题:任何人都可以详细说明这种行为吗?
澄清:我知道可以通过在函数定义中指定数组大小来"解决"这个问题.那不是我感兴趣的东西.
对于"奖励"积分:任何人都可以通过以下消息拒绝第10行时确认MSVC 2010是错误的吗?
1><snip>\prog.c(10): warning C4048: different array subscripts : 'int (*)[]' and 'int (*)[3]'
Run Code Online (Sandbox Code Playgroud)
Dan*_*her 14
n1570的6.5.2.1节,数组下标:
约束
其中一个表达式应具有类型''指向完整对象类型'的指针,另一个表达式应具有整数类型,结果具有类型''type''.
所以标准禁止表达式p[0]if if p是指向不完整类型的指针.对于间接运算符没有这样的限制*.
但是,在标准的旧版本/草稿中(n1256和C99),该段落中没有"完整"一词.在标准程序中没有涉及任何方式,我只能猜测这是一个突破性的变化还是一个疏忽的纠正.编译器的行为表明后者.这是因为p[i]每个标准都是相同的,*(p + i)并且后一个表达式对于指向不完整类型的指针没有意义,所以为了p[0]工作如果p是指向不完整类型的指针,则需要一个明确的特殊情况.
我的 C 有点生疏,但我的理解是,当你有一个int (*p)[]这样的:
(*p)[n]
Run Code Online (Sandbox Code Playgroud)
说“取消引用p以获得一个整数数组,然后取第 n 个”。这似乎很自然地得到了很好的定义。而这:
p[n][m]
Run Code Online (Sandbox Code Playgroud)
说“取 p 中的第 n 个数组,然后取该数组的第 m 个元素”。这似乎根本没有明确定义;您必须知道数组有多大才能找到第 n 个数组的开始位置。
这可能适用于 n = 0 的特定特殊情况,因为无论数组有多大,第 0 个数组都很容易找到。您只是发现 GCC 无法识别这种特殊情况。我不知道详细的语言规范,所以我不知道这是否是一个“错误”,但我个人在语言设计方面的品味是p[n][m]应该有效还是无效,而不是在n静态已知时它应该有效为 0 而不是其他。
是*p <===> p[0]真正从语言规范的明确规则,或只是一个观察?在我编程时,我不认为取消引用和零索引是相同的操作。