【发布时间】:2023-03-22 07:50:02
【问题描述】:
场景:
$ cat t0.c t1.c
/* t0.c */
int i = 12;
/* t1.c */
int i INIT;
int main(void)
{
return 0;
}
$ gcc t0.c t1.c -DINIT="" -std=c11 -pedantic
<nothing>
$ gcc t0.c t1.c -DINIT="=0" -std=c11 -pedantic
ld: /tmp/ccrTTgwH.o:(.bss+0x0): multiple definition of `i'; /tmp/cckd6R4u.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
为什么=0 很重要?
更新:
dvl-linux64 $ gcc82 --version
gcc-8.2 (GCC) 8.2.0
试试gcc 11.2.0:
$ gcc t0.c t1.c -DINIT="" -std=c11 -pedantic
ld: /tmp/ccmPBPUT.o:t1.c:(.bss+0x0): multiple definition of `i';
$ gcc t0.c t1.c -DINIT="=0" -std=c11 -pedantic
ld: /tmp/ccxw378s.o:t1.c:(.bss+0x0): multiple definition of `i';
预期。
决赛桌:
compiler -DINIT="" leads to multiple definition of `i'?
gcc 8.2.0 NO
gcc 11.2.0 YES
clang 8.0.1 NO
clang 13.0.0 YES
【问题讨论】:
-
外部变量只能初始化一次。如果一个文件显示
i = 12而另一个文件显示i = 0,则不能将它们链接在一起。 -
为什么 -D INIT 被替换为 "=0", "int i;"与“int i = 0;”非常不同
-
当我尝试这两个命令时,都会导致
i的多个定义。 -
...确实在这两种情况下都有多个定义,尽管从历史上看,一些编译器已接受这种情况作为扩展,但需要注意各种警告。
-
一个 extension 在许多传统的 Unix 编译器中默认启用,包括 GCC 直到最近。在最新版本的 GCC 中,您需要启用
-fcommon才能获得旧的行为。 (在旧的 GCC 中,-fno-common将关闭该扩展。)
标签: c initialization global-variables c11