В настоящее время я пытаюсь понять, как работают компилятор gcc и компоновщик. Я столкнулся с очень интересной техникой, называемой «подстановкой во время ссылки». Цель состоит в том, чтобы иметь несколько определений функции в нескольких файлах и решить, какое из этих определений войдет в окончательный исполняемый файл во время компоновки.
Простой пример:
main.c:
#include "header.h"
int main(void)
{
hello("everyone");
return 0;
}
header.h:
#ifndef _HEADER_H
#define _HEADER_H
void hello(const char * name);
#endif
file1.c:
#include "header.h"
#include <stdio.h>
void hello(const char * name)
{
printf("File1: Hello, %s!\n", name);
}
file2.c:
#include "header.h"
#include <stdio.h>
void hello(const char * name)
{
printf("File2: Hello, %s!\n", name);
}
Теперь у меня два вопроса:
Надеюсь, мои вопросы понятны;)
Спасибо!
Не связаны с вашей проблемой и вопросом, но символы, начинающиеся с подчеркивания и за которыми следует заглавная буква (например, _HEADER_H), являются зарезервированный во всех областях для «реализации» (компилятор и стандартная библиотека).
Да, я могу редактировать file2. Переключатели препроцессора, безусловно, являются решением этой проблемы, но мне было интересно, есть ли более элегантный способ, возможно, за счет умного использования компоновщика (я особенно пытаюсь понять, как порядок аргументов играет роль во время связывания).
@ Какой-то чувак-программист: Спасибо за пояснение, не знал об этом! ;)
Вы можете отметить одну функцию как слабый символ.





Is it possible to select a function by using an appropriate linking order (if all three files appear in the linker's argument list)?
Если под «всеми тремя файлами» вы подразумеваете объектные файлы (и при условии отсутствия слабых символов), тогда нет: все 3 файла будут связаны, и вы получите ошибку определения повторяющегося символа.
Но если вы поместите 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
Suppose file2.c implements many functions which are needed by main.c. Is it possible to replace a single function or some functions by different implementations in file1.c (with the same name) by using the linker?
Да, но только на платформах, поддерживающих слабые символы (например, платформы ELF, см. __attribute__((weak))здесь).
Если все символы в 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
Вы можете редактировать file2? В этом случае я бы выбрал функцию для более явного использования. Например. инкапсулировать в условные части с помощью переключателей препроцессора.