【问题标题】:Tentative definition of struct with incomplete type不完整类型结构的暂定定义
【发布时间】: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


【解决方案1】:

是的,这是未定义的。

未定义的行为正是该术语所表示的,它不是由标准定义的。任何编译器都可以添加自己的定义,从而扩展标准,并且没有义务诊断其中的任何一个。特别是,gcc 对暂定定义有一些特殊的想法。使用这些的代码不可移植。

【讨论】:

  • 回复。非静态对象,您能否发布一个解释它们的链接或一个或两个示例。它们听起来很糟糕,这就是为什么我可能从未使用过它们,因此不确定它们是什么。 猜测,这可能是:static int foo; extern int foo; 在文件范围内???
  • 抱歉,我忽略了您在暂定定义中的static
猜你喜欢
  • 1970-01-01
  • 2016-01-21
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-28
  • 2022-01-09
相关资源
最近更新 更多