9

我有两个源文件:

源文件 1(assembler.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

4 回答 4

13

首先,包含源文件在 C 编程中是一种不好的做法。通常,当前翻译单元应该由一个源文件和一些包含的头文件组成。

在您的情况下发生的情况是您有两个parse_file函数副本,每个翻译单元中都有一个。编译成目标文件时parser.c,有自己的parse_file功能,assembler.c也有自己的。

当给定两个目标文件作为输入时,抱怨的是链接器(而不是编译器),每个目标文件都包含自己的parse_file.

您应该像这样重组您的项目:

解析器.h

void parse_file(char *);

解析器.c

void parse_file(char *src_file) {
    // Function here
}

汇编程序.c

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

int main (void) {
    parse_file("test.txt");
    return 0;
}
于 2011-10-03T18:16:28.740 回答
8

您包含 parser.c 文件,这意味着该文件中的所有代码都将“复制”到 assembler.c 文件。这意味着编译器在编译parser.c时会编译parser.c的全部内容,然后在编译器编译assembler.c时会再次编译

这就是标题的用途。
在标题中您只能放置声明,因此您可以包含它而无需在不同的翻译单元中再次创建相同的符号。

所以你可以创建一个 parser.h 只包含函数的声明:

void parse_file(char *config_file);

然后在您的 assembler.c 中,您只包含标题:

#include "parser.h" //include the header, not the implementation
int main() {
    parse_file("test.txt");
    return 0;
}
于 2011-10-03T18:13:54.933 回答
3

您正在包括包含函数 parse_file 定义的 .c 文件。因此它被定义了两次,一次在每个翻译单元中,这是不允许的。

于 2011-10-03T18:14:56.583 回答
2

正如其他答案所述,包括源意味着文件将被复制到parser.c并将在原始位置(assembler.c)中定义。要解决此问题,请使用您的原型创建一个头文件:

解析器.h

void parse_file(char *config_file);

并包含文件:

汇编程序.c

#include "parser.h"
int main() {
    parse_file("test.txt");
    return 0;
}

或者删除包含并提供函数的线索:

int main() {
    void parse_file(char *);
    parse_file("test.txt");
    return 0;
}

或者甚至只是简单地删除包含。不好的做法,因为编译器(没有关于函数的信息)会认为它的返回值是一个整数,并且可能会导致其他警告。

于 2011-10-03T18:21:42.610 回答