Дубликат символа в C - PullRequest
       6

Дубликат символа в C

9 голосов
/ 03 октября 2011

У меня есть два исходных файла:

Исходный файл 1 (assemblyr.c):

#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 ]

11 голосов
/ 03 октября 2011

Прежде всего, включая исходные файлы, это плохая практика в программировании на Си.Обычно текущая единица перевода должна состоять из одного исходного файла и нескольких включенных заголовочных файлов.

В вашем случае происходит то, что у вас есть две копии функции 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
}

assemblyr.c

/* note that the header file is included here */
#include "parser.h"

int main (void) {
    parse_file("test.txt");
    return 0;
}
8 голосов
/ 03 октября 2011

Вы включаете файл parser.c, что означает, что весь код в этом файле будет «скопирован» в файл assemblyr.c. Это означает, что все содержимое файла parser.c будет скомпилировано, когда компилятор компилирует parser.c, а затем оно будет скомпилировано снова, когда компилятор компилирует ассемблер.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;
}
3 голосов
/ 03 октября 2011

Вы включаете файл .c, который содержит определение функции parse_file. Таким образом, он определяется дважды, один раз в каждой единице перевода, что недопустимо.

2 голосов
/ 03 октября 2011

Как указано в других ответах, в том числе источник означает, что файл будет скопирован в 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. Не очень хорошая практика, так как компилятор (без информации о функции) будет считать, что возвращаемое значение является целым числом и может вызывать другие предупреждения.

...