gpt4 book ai didi

c++ - C 与 C++ 中的枚举存储差异

转载 作者:可可西里 更新时间:2023-11-01 16:36:07 26 4
gpt4 key购买 nike

我在移植到 C++ 的 C 项目中遇到了以下构造;

enum TestEnum 
{
A=303,
B=808
} _TestEnum;

int foo()
{
_TestEnum = B;
}

当使用 GCC 编译并查看生成的代码时,我得到:

nils@doofnase ~ $ gcc -std=c90 -O2 -c ./test.c -o test.o
nils@doofnase ~ $ size test.o
text data bss dec hex filename
59 0 0 59 3b test.o

因此使用了零字节的数据或 BSS 段。

另一方面,如果我用 C++ 编译,我得到:

nils@doofnase ~ $ g++ -std=c++11 -O2 -c ./test.c -o test.o
nils@doofnase ~ $ size test.o
text data bss dec hex filename
59 0 4 63 3f test.o

我看到 BSS 中分配了四个字节的存储空间,正如我所期望的那样。

此外,在 C 项目中,枚举定义实际上位于一个头文件中,该头文件包含在多个 c 文件中。该项目编译和链接都很好。当编译和链接为 C++ 时,编译器会提示 _TestEnum 是在多个对象中定义的(没错!)。

这是怎么回事?我在看一些古老的 C 语言特例吗?

编辑:为了完整起见,这是 gcc 版本:

nils@doofnase ~ $ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609

最佳答案

默认情况下,GCC 编译器启用 C 扩展(即使 -pedantic 标志有效),它允许跨 translation units 对象的多个外部定义。 .

引用 C11 (N1570) J.5.11 多个外部定义(资料部分):

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

请注意,依赖此行为的应用程序并不严格符合 ISO C 语言。更具体地说,C11 6.9/p5 外部定义声明(强调我的):

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.161)

从技术上讲,违反该规则会调用 undefined behavior ,这意味着实现可能会也可能不会发出诊断消息。

你可以检查,这个扩展已经被 nm 命令启用:

nm test.o 
0000000000000000 T foo
0000000000000004 C _TestEnum

根据man nm:

"C" The symbol is common. Common symbols are uninitialized data. When linking, multiple common symbols may appear with the same name. If the symbol is defined anywhere, the common symbols are treated as undefined references.

要禁用此扩展,您可以使用 -fno-common旗帜。来自 GCC 文档:

Unix C compilers have traditionally allocated storage for uninitialized global variables in a common block. This allows the linker to resolve all tentative definitions of the same variable in different compilation units to the same object, or to a non-tentative definition. This is the behavior specified by -fcommon, and is the default for GCC on most targets.

关于c++ - C 与 C++ 中的枚举存储差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48126305/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com