c - 当有两个具有相同符号但不同类型的全局变量的 .c 文件时,引用如何工作?

标签 c linker global-variables

C

假设我有以下 C 模块:

模块 1

#include <stdio.h>
int x;
int main(){
  foo();
  printf("%i\n",x);
  return 0;
}

模块 2

double x;
void foo(){
  x = 3.14;
}

我的问题是:链接器在这种情况下做了什么?在我正在阅读的教科书中,它说编译器只为链接器符号表选择两个弱全局变量之一。这两个选哪个?还是两者都选?如果是这样,为什么?谢谢。

最佳答案

C 说这是未定义的行为。

(C99, 6.9p5) "If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof 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"

未定义行为意味着链接器可以在存在多个外部对象定义的情况下中止链接过程。

现在链接器很好(或者邪恶,你可以选择)并且通常有默认扩展来处理多个外部对象定义并且在某些情况下不会失败。

如果您使用来自 binutils 的 gccld,如果您的两个对象被显式初始化,您将收到错误消息。例如,您在第一个翻译单元中有 int x = 0;double x = 0.0;

否则,如果外部对象之一未明确初始化(您示例中的情况),gcc 将静默地将两个对象合并为一个符号。您仍然可以通过向链接器传递选项 --warn-common 来要求链接器报告警告。

例如链接模块时:

gcc -Wl,--warn-common module1.o module2.o

要中止链接过程,您可以使用 --fatal-warnings 选项请求链接器将所有警告视为错误(-Wl,--fatal-warnings,--警告-常见)。

另一种中止链接过程的方法是使用-fno-common 编译器选项,如@teppic 所述。在他的回答中。 -fno-common 禁止外部对象在编译时获得 Common 符号类型。如果你对两个模块都这样做然后链接,你也会得到多重定义链接器错误。

gcc -Wall -fno-common -c module1.c module2.c

gcc module1.o module2.o

关于c - 当有两个具有相同符号但不同类型的全局变量的 .c 文件时,引用如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15604274/

相关文章:

java - 如何在 C 中使用 Long 数据类型?

c - 找不到 DEADLINE 调度策略

c++ - 我正在尝试使用队列实现 bfs。有人可以帮我找到错误吗?

c - 如何在C中压缩字符串的元素

php - 如何使用 Javascript/PHP/MySQL 定义和使用站点级别 "User Privilege Level"变量

r - 在 GUI 中使用 R 引用类将值从一个窗口传递到另一个窗口

c++ - Visual Studio 代码 clang 错误 : linker command failed with exit code 1 on Mac

c++ - 如何在 Eclipse CDT 中将静态库链接到静态库

c++ - 链接问题与 g++ 有关,但与 cc 无关

c++ - 在 main 之前调试对全局变量的赋值