gcc:链路时间替换

gcc:链路时间替换,c,gcc,linker,C,Gcc,Linker,我目前正试图了解gcc编译器和链接器是如何工作的。我遇到了一种叫做“链接时间替换”的技术,我觉得这很有趣。目标是在多个文件中有一个函数的多个定义,并决定在链接期间哪些定义进入最终可执行文件 一个简单的例子: 主要条款c: #include "header.h" int main(void) { hello("everyone"); return 0; } 标题h: #ifndef _HEADER_H #define _HEADER_H void hello(const ch

我目前正试图了解gcc编译器和链接器是如何工作的。我遇到了一种叫做“链接时间替换”的技术,我觉得这很有趣。目标是在多个文件中有一个函数的多个定义,并决定在链接期间哪些定义进入最终可执行文件

一个简单的例子:

主要条款c:

#include "header.h"

int main(void)
{
    hello("everyone");
    return 0;
}
标题h:

#ifndef _HEADER_H
#define _HEADER_H

void hello(const char * name);

#endif
文件1.c:

#include "header.h"
#include <stdio.h>

void hello(const char * name)
{
    printf("File1: Hello, %s!\n", name);
}
#包括“header.h”
#包括
void hello(常量字符*名称)
{
printf(“文件1:Hello,%s!\n”,名称);
}
文件2.c:

#include "header.h"
#include <stdio.h>

void hello(const char * name)
{
    printf("File2: Hello, %s!\n", name);
}
#包括“header.h”
#包括
void hello(常量字符*名称)
{
printf(“文件2:Hello,%s!\n”,名称);
}
现在我有两个问题:

  • 是否可以使用适当的链接顺序来选择函数(如果链接器的参数列表中显示了所有三个文件)
  • 假设file2.c实现了main.c所需的许多函数。是否可以使用链接器用file1.c中的不同实现(同名)替换单个函数或某些函数?链接器应该首先使用file1.c中的函数定义,然后使用file2.c处理剩余的未解析函数
我希望我的问题可以理解;)

谢谢

是否可以使用适当的链接顺序来选择函数(如果链接器的参数列表中显示了所有三个文件)

如果“所有三个文件”是指对象文件(并且假设没有弱符号),则否:所有三个文件都将链接进来,并且您将得到一个重复的符号定义错误

但是,如果将file1.o放入lib1.a,将file2.o放入lib2.a,则是:

gcc main.c -l1 -l2  # uses file1.o:hello
gcc main.c -l2 -l1  # uses file2.o:hello
更多细节和细节

假设file2.c实现了main.c所需的许多函数。是否可以使用链接器用file1.c中的不同实现(同名)替换单个函数或某些函数

是的,但仅在支持弱符号的平台上(如ELF平台,请参阅
\uuuuu属性\((弱))

如果file2.o中的所有符号都是弱定义的,而file1.o中的所有符号都不是弱定义的,那么链接file1.o和file2.o将获得所需的结果:强符号获胜

我相信(但尚未测试)如果file1.o和file2.o都弱定义了相同的符号,那么顺序将很重要:

gcc main.c file1.o file2.o  # file1.o definitions override file2.o
gcc main.c file2.o file1.o  # file2.o definitions override file1.o

你能编辑文件2吗?在这种情况下,我会选择以更明确的方式使用的函数。例如,在预处理器开关的帮助下封装在条件部分。与您的问题和问题无关,但以下划线开头并后跟大写字母的符号(如
\u HEADER\u H
)保留在“实现”(编译器和标准库)的所有范围内。是的,我可以编辑文件2。预处理器切换当然是这个问题的解决方案,但我想知道是否有更优雅的方式,也许是通过巧妙地使用链接器(我特别想了解参数的顺序在链接过程中是如何起作用的)。@一些程序员伙计:谢谢你的澄清,我不知道!)可以将一个函数标记为。