在文件struct_test.c中,我这样写:

static struct x x;

我用GCC编译(4.8.2,Ubuntu)
gcc -c -O0 struct_test.c

我得到了可以理解的错误:
error: storage size of 'x' isn't known

然后我重新编译,这次打开了优化
gcc -c -O struct_test.c

并且文件编译没有错误。

我可以理解为什么打开优化功能可以消除该错误,但是有人可以帮助我获得实际的编译器选项,该选项指示gcc忽略未定义的标记“x”吗?

最佳答案

当它出现在文件范围内时,此代码:

static struct x x;
声明xstruct x类型的对象并具有内部链接。无需事先声明struct x类型:

(C99 6.7.2.3/8)
在翻译单元中首次遇到的结构或 union 类型不完整,但是可以稍后在该翻译单元中完成:

(C99 6.2.5/22)
C区分通常指定对象类型的“声明”和指定类型并导致保留存储的“定义”。在给定的翻译单元中,不是定义的声明可能具有不完整的类型,而该类型在该单元中永远不会完成。
C99的第6.9.2节指定了哪些文件作用域对象声明是定义:
  • 具有文件范围和初始化程序的声明是一个定义(特别是“外部定义”,即使它定义的对象可能具有内部链接)
  • 带有文件范围且没有初始化程序,具有静态存储类或无存储类说明符的
  • 声明是“临时定义”。如果转换单元不包含同一对象的外部定义,则行为就好像存在一个具有初始化程序0的外部定义。

  • 本节还规定:“如果对象标识符的声明是一个临时定义,并且具有内部链接,则声明的类型不得是不完整的类型。”这在这里适用,但是由于可以通过以后的声明来完成翻译单元中某一时刻不完整的类型,因此它不会固有地使所讨论的代码行无效。但是,它会使仅包含该行的翻译单元无效。
    那么,GCC发生了什么?
    由于给出的代码(作为完整的翻译单元)违反了“不得”的语言约束,因此会产生未定义的行为。 GCC没有义务拒绝代码或进行任何类型的诊断,尽管允许GCC进行其中之一或全部执行。事实证明,如果gcc-Wall标志处于打开状态,则不管优化级别如何,-pedantic都会发出有关代码的警告。无论如何,gcc明确否认是用于验证代码标准合规性的工具。
    但是,这种特殊的侵犯是相对良性的。由于从未引用过该对象,因此gcc可以假装甚至从未声明过该对象,而不会冒错误或意外行为的风险。-fdce(死代码消除)选项似乎是一个影响此特定行为的选项。奇怪的是,尽管-fdce足以在优化级别O0上抑制错误,但-fno-dce并没有将其带回到更高的优化级别。

    关于c - 开启优化功能后,GCC未报告结构存储大小错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30080457/

    10-11 23:18
    查看更多