假设有以下代码:
File a.c
#include <stdio.h>
int a;
int func();
int main(int argc, char **argv) {
a = 7;
int a2 = func();
printf("a is %d, a2 is %d\n", a, a2);
return 0;
}
File b.c
int a;
int func()
{
a = 9;
return a;
}
当编译时g++ a.c b.c -Wall -O0
,正如预期的那样,它会产生链接错误。然而,当调用gcc a.c b.c -Wall -O0
它不会产生任何警告或错误!
输出是a is 9, a2 is 9
顺便一提。
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
为什么海湾合作委员会允许这样做?
我对这种行为感到惊讶。如果在声明时初始化变量,则 GCC 的链接也会失败。
当编译时g++ a.c b.c -Wall -O0
正如预期的那样,它会产生链接错误。然而,当调用gcc a.c b.c -Wall -O0
它不会产生警告,也不会产生错误!
在你的代码中,a
has a 暂定定义(这变成了full定义在当前翻译单元的末尾),这在 C 中是有效的。
然而,还有另一个这样的暂定定义,它成为一个完整的定义b.c
来自另一个翻译单元——两者都提供了外部定义a
在你的程序中。换句话说,a.c
and b.c
它们本身就很好,但是当它们组合在一起编译时(无论是直接编译还是将它们编译成单独的模块,然后通过链接它们来生成可执行文件),它都是无效的。这是未定义的行为:
C11,6.9/5 https://port70.net/%7Ensz/c/c11/n1570.html#6.9p5:
外部定义是外部声明,也是函数的定义(内联定义除外)或对象。如果在表达式中使用通过外部链接声明的标识符(除了作为结果为整型常量的 sizeof 或 _Alignof 运算符的操作数的一部分),则在整个程序中的某处应该有一个该标识符的外部定义;否则,不得超过一个。161
然而,这通常作为 GCC 的扩展来支持。这就是为什么当你调用gcc
,它可以很好地编译为 C 代码。严格来说(标准而言),这是 C 中的无效代码。
当你调用g++
将其编译为 C++ 代码会失败,因为 C++ 没有暂定定义。它在 C++ 中无效。因此,g++
错误输出。看一种定义规则 https://en.cppreference.com/w/cpp/language/definition in C++.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)