c - 多次声明全局变量时 GCC 没有警告或错误

标签 c gcc

<分区>

假设如下代码:

文件 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;
}

文件 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是9,a2是9

gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)

为什么 GCC 允许这样做?

我对这种行为感到惊讶。如果您在声明时初始化变量,则 GCC 的链接也会失败。

最佳答案

When compiled with g++ a.c b.c -Wall -O0 it produces a linking error, as expected. However, when invoking gcc a.c b.c -Wall -O0 it produces no warning and no error!

在您的代码中,a 有一个暂定定义(在当前翻译单元的末尾变成一个完整定义)它是在 C 中有效。

然而,还有另一个这样的暂定定义,它成为来自另一个翻译单元的 b.c 中的完整定义——它们都为您的程序中的 a 提供了外部定义。换句话说,a.cb.c 单独使用没问题,但是当它们组合在一起编译时(您直接编译或将它们编译成单独的模块,然后通过链接它们来制作可执行文件)。这是未定义的行为:

C11, 6.9/5 :

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

然而,这通常作为扩展被 GCC 支持。这就是为什么当您调用 gcc 时,它可以像 C 代码一样很好地编译。严格来说(标准方面),这是 C 中的无效代码。

当您调用 g++ 将其编译为 C++ 代码时,它会失败,因为 C++ 没有临时定义。它在 C++ 中无效。因此,g++ 出错了。参见 One Definition Rule在 C++ 中。

关于c - 多次声明全局变量时 GCC 没有警告或错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42261812/

相关文章:

c - 删除硬件id对应的oem.inf文件

c - 指向 char[] 的双指针

c - 插入有序链表并省略重复节点

c99 转到过去的初始化

c - 多线程服务器如何工作?

c++ - BCB swprintf 不工作

c - 了解空 main() 到程序集的翻译

c - 简单的 ADD/ADC ARM 组件失败

c++ - 如何在 Ubuntu 12.0.4 上安装 GCC 2.95?

c - 为什么 sizeof ('3' ) == 4 使用 GCC 编译器?