【发布时间】:2018-09-26 13:56:26
【问题描述】:
将以下内容视为 C 文件:
static struct S a;
int main() {
return (long)&a;
}
struct S {
int b;
} s;
根据我对C11 spec 的阅读,我认为这是未定义的行为。 6.9.2 状态:
具有文件作用域的对象的标识符声明没有初始值设定项、没有存储类说明符或具有存储类说明符 static,构成一个暂定定义。
在语义标题下(不是约束):
如果一个对象的标识符声明是一个暂定定义并且具有内部链接,则声明的类型不能是不完整的类型。
第一行的声明似乎是一个暂定定义,对象a有内部链接,而struct S在声明时类型不完整。所以,我希望这会违反第二个引号,从而导致未定义的行为。
但是,使用 --std=c11 -Wall -pedantic 标志运行时,GCC 不会打印任何诊断信息。我误解了标准,还是 GCC 没有为这种未定义的行为打印诊断信息?
【问题讨论】:
-
FWIW clang 生成以下警告:"警告:具有内部链接的变量的暂定定义具有不完整的非数组类型 'struct S' [-Wtentative-definition-incomplete-type]"
-
GCC 试图产生一个合理的结果而不是拒绝代码,尽管
-pedantic -std=c11限制了它将接受的内容。所示程序中a的地址不需要依赖于a的类型(以及大小);这可能是您侥幸逃脱的部分原因。如果在结构类型完成后添加一个访问a的函数(并调用该函数),是否会发生任何变化?然而,这绝对不是答案——这只是偶然的观察。 -
旁白:如果地址不适合
long,则(long)&a;是UB。 -
@chux 不是 UB,而是实现定义的行为。 6.3.2.3/5.
-
@SomeName:顺便说一句,我想不出一个真正的用例来临时定义具有不完整类型的外部链接的标识符。我希望它会发生;一个可能的原因可能是自动生成的代码。但我没有什么要指出的。
标签: c language-lawyer c11