仔细阅读标准可以明确,在C99和C11中,声明应该是一个约束违规。
C11 6.7.2.6 Array declarations p1
此外,除了可选的类型限定符和关键字static之外,
[
和
]
还可以界定表达式或
*
。如果它们界定了一个表达式(指定数组的大小),则该表达式应具有整数类型。如果表达式是常量表达式,则其值应大于零。
元素类型不应为不完整或函数类型。可选的类型限定符和关键字static只应出现在具有数组类型的函数参数的声明中,并且只应出现在最外层的数组类型派生中。
由于这包含对
*
的引用,该符号仅在非定义的函数声明中有效,而其他地方无效,因此整个约束需要视为适用于参数。
对于C90来说,情况更为复杂。这实际上在1992年12月10日的C90
缺陷报告47中讨论过。
其中6个声明中的2个如下:
struct S;
struct S *g(struct S a[]) { return a; }
缺陷报告询问这些是否严格符合规范。需要注意的是,与问题不同,这些是属于定义而不仅仅是声明的原型。
尽管如此,标准委员会回应说
struct S
是不完整类型(子句6.5.2.3,第62页,第25-28行)。此外,未知大小的数组也是不完整类型(子句6.5.4.2,第67页,第9-10行)。因此,任何一个上述数组都不是严格符合规范的(子句6.1.2.5,第23页,第23-24行)。这使得声明3、4和6不是严格符合规范的。(但实现可能会做正确。)
顺便说一下,数组参数被调整为指针类型(子句6.7.1,第82页,第23-24行)。然而,没有什么迹象表明,一个不严格符合规范的数组类型可以通过这个规则神奇地变成严格符合规范的指针参数。
所涉及的类型可以有两种不同的解释方式。(数组到指针的转换可以尽早或尽晚发生。)因此,使用这种形式的程序具有未定义的行为。
(我强调)
自1992年以来,这一行为没有得到书面澄清,因此我们必须同意该行为是未定义的,因此C标准没有任何要求,一个成功编译此代码的编译器仍然符合C90标准。
委员会还指出,在C90中不存在任何约束违规,因此符合C90标准的编译器不需要输出任何诊断信息。
我编辑了答案;我之前声称这适用于C99和C11,但是在C99中更改了文本,因此这是C99、C11中的约束违规。