在文件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'?
答案 0 :(得分:4)
当它出现在文件范围时,此代码:
static struct x x;
将x
声明为struct x
类型的对象并具有内部链接。之前不需要声明struct x
类型:
如果形式
struct-or-union identifier
的类型说明符不是[在结构类型声明中],并且标识符的其他声明都不可见,那么它声明了一个不完整的结构或联合类型,并且将标识符声明为该类型的标记。
(C99 6.7.2.3/8)
在翻译单元中首次遇到时不完整的结构或联合类型仍然可以在该翻译单元中稍后完成:
未知内容的结构或联合类型[...]是不完整类型。对于该类型的所有声明,通过在稍后的同一范围内声明相同的结构或联合标记及其定义内容,它已完成。
(C99 6.2.5 / 22)
C通常区分“声明”,它指定对象的类型,和“定义”,它们都指定类型并导致要保留的存储。在给定的翻译单元中,非定义的声明可能具有在该单元内从未完成的不完整类型。
C99的第6.9.2节规定了哪些文件范围对象声明是定义:
0
的外部定义。本节还规定“如果对象的标识符声明是暂定定义并且具有内部链接,则声明的类型不应是不完整的类型。”这适用于此,但由于翻译单元中某一点处不完整的类型可以通过稍后的声明来完成,因此它本身并不会使所讨论的代码行无效。但是,它 使仅包含该行的翻译单元无效。
由于作为完整翻译单元的代码违反了“不应该”的语言约束,因此会产生未定义的行为。 GCC没有义务拒绝代码或产生任何类型的诊断,但允许其中一种或两种都做。事实证明,无论优化级别如何,gcc
都会在启用-Wall
或-pedantic
标记时发出有关代码的警告。无论如何,gcc
明确拒绝成为验证代码标准合规性的工具。
然而,这种特殊的违规行为相对温和。因为永远不会引用该对象,所以gcc
可以假装它甚至从未声明过而不会冒错误或意外行为。
-fdce
(死代码消除)选项似乎是影响此特定行为的选项。奇怪的是,虽然-fdce
足以抑制优化级别O0
的错误,但-fno-dce
并未将其恢复到更高的优化级别。