c - 链接器如何解析在多个位置定义的同名全局符号

标签 c

我是编程新手,我从 c 开始。我正在学习链接器如何解析在多个地方定义的全局符号。所以我做了一个小程序,上面写着:

//main.c

#include <stdio.h>

void b(void);


int x;
int a=10;
int y =500;
int x1 = 2016;

int main()
{
b();


printf("x = %1f y = %d\n",x , y);
return 0;
}

//第二个文件.c

double x=100.0;
int g=100;
extern int y;
void b()
{
x = -100.0;

}

我从链接器解决这种情况所遵循的规则中知道,链接器将选择强符号,在本例中为 (double x=100.0;),而不是 main.c 中定义的整数。所以我预计输出为 x=-100.0 y=500, 但输出是 x=0.000000 y=89 谁能解释一下为什么我会找到这个输出或者我错在哪里?

我尝试在cmd(适用于Windows)中使用objdump命令来查看符号表,我可能会发现一些让我理解的东西,但我发现另一件事很奇怪,我发现变量的地址如下:

a------ 0x00000000

y------0x00000004

x1-----0x00000008

x------ 0x00000010

g------ 0x00000018

我认为 x 应该从 0x0000000c 开始,为什么不呢?

最佳答案

您可能知道也可能不知道,您需要小心使用多个定义。理想情况下,每个全局符号都将被精确定义一次。在多种情况下,您可以避免使用多个定义,但您必须小心。

在这种情况下,您依赖于“通用分配模型”,无论您相信与否,该模型在 C 编译器中曾经(并且仍然)广泛使用,因为它受到了 FORTRAN 的早期影响。该模型表明,您可以有多个定义,只要最多其中一个定义给出初始值即可。但是 - 这是最重要的 - 所有定义必须具有相同的类型。 (我不确定我是否见过这条规则;我不确定我是否明确地考虑过它,因为最终很明显它必须如此。)

C 使用单独编译的概念。每个 .c 文件都会编译为一个单独的、独立的“目标文件”。随后,一个名为链接器的单独程序将目标文件链接在一起。链接器将最终地址分配给全局变量,并最终解决公共(public)分配问题。

但是链接器只解析地址。它将安排 main.c 中的 xsecond_file.c 中的 x 位于同一地址。但是,如果 main.c 认为在位置 x 处有一个 int,那么它将如何解释它。如果 second_file.c 认为位置 x 处有一个 double,并且确实在那里存储了 double 类型的值,当 main.c 尝试将该位模式解释为 int 时,将会出现乱码。

正如 @user58697 在另一个答案中讨论的那样,您在 printf 调用中遇到了其他问题,尝试使用 %f 进行打印(编译器认为是什么) int 值,这也永远无法正常工作。

关于c - 链接器如何解析在多个位置定义的同名全局符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50957847/

相关文章:

c - OpenGL/OSX/GLFW : nothing except the window color

C 代码,随机骰子游戏未给出正确答案需要帮助

c++ - 内存到文件回到内存

c - 如何获得不易受骗的时间戳

c - 使用管道写入和读取 Int 数组

结合静态库

c - 使用填充防止虚假共享

Android 无法解析类型 ulong64

c - C : Character sequences recognized as such and simulating line breaks 中换行的必要性

c - 为什么我的系统中有这么多版本的头文件?