Дубликат символа в C
У меня есть два исходных файла:
Исходный файл 1 (ассемблер.с):
#include "parser.c"
int main() {
parse_file("test.txt");
return 0;
}
Исходный файл 2 (parser.c):
void parse_file(char *config_file);
void parse_file(char *src_file) {
// Function here
}
Почему-то при компиляции выдает следующую ошибку:duplicate symbol _parse_file in ./parser.o and ./assembler.o for architecture x86_64
Почему это дает мне дубликат символа для parse_file? Я просто вызываю функцию здесь... Нет?
4 ответа
Прежде всего, включение исходных файлов - плохая практика в программировании на Си. Обычно текущая единица перевода должна состоять из одного исходного файла и нескольких включенных заголовочных файлов.
Что происходит в вашем случае, что у вас есть две копии parse_file
функция, по одному в каждой единице перевода. когда parser.c
скомпилирован в объектный файл, он имеет свой собственный parse_file
функция и assembler.c
тоже есть своя.
Это компоновщик, который жалуется (не компилятор), когда в качестве входных данных предоставляется два объектных файла, каждый из которых содержит свое собственное определение parse_file
,
Вы должны реструктурировать свой проект следующим образом:
parser.h
void parse_file(char *);
parser.c
void parse_file(char *src_file) {
// Function here
}
assembler.c
/* note that the header file is included here */
#include "parser.h"
int main (void) {
parse_file("test.txt");
return 0;
}
Вы включаете файл parser.c, что означает, что весь код в этом файле будет "скопирован" в файл assemblyr.c. Это означает, что все содержимое файла parser.c будет скомпилировано, когда компилятор компилирует parser.c, а затем оно будет скомпилировано снова, когда компилятор компилирует ассемблер.
Вот для чего нужны заголовки.
В заголовке вы можете поместить только объявления, так что вы можете включить их, не создавая те же символы снова в другой единице перевода.
так что вы можете просто создать parser.h, содержащий только объявление функции:
void parse_file(char *config_file);
тогда в вашем ассемблере вы включаете только заголовок:
#include "parser.h" //include the header, not the implementation
int main() {
parse_file("test.txt");
return 0;
}
Вы включаете файл.c, который содержит определение функции parse_file. Таким образом, он определяется дважды, один раз в каждой единице перевода, что недопустимо.
Как указано в других ответах, в том числе источник означает, что файл будет скопирован в parser.c и будет определен там же в исходном месте (assemblyr.c). Чтобы решить эту проблему, либо создайте файл заголовка с вашим прототипом:
parser.h
void parse_file(char *config_file);
И включите этот файл:
assembler.c
#include "parser.h"
int main() {
parse_file("test.txt");
return 0;
}
Или удалите include и предоставьте ключ к функции:
int main() {
void parse_file(char *);
parse_file("test.txt");
return 0;
}
Или даже просто удалите включение в al. Не очень хорошая практика, так как компилятор (без информации о функции) будет считать, что возвращаемое значение является целым числом и может вызывать другие предупреждения.