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 的 gcc
和 ld
,如果您的两个对象被显式初始化,您将收到错误消息。例如,您在第一个翻译单元中有 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/