C中的重复符号

时间:2011-10-03 18:10:52

标签: c function duplicate-symbol

我有两个源文件:

Source FIle 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 个答案:

答案 0 :(得分:11)

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

在您的情况下,您有两个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;
}

答案 1 :(得分:8)

您包含parser.c文件,这意味着该文件中的所有代码都将“复制”到assembler.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;
}

答案 2 :(得分:3)

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

答案 3 :(得分:2)

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

parser.h

void parse_file(char *config_file);

并包含那个文件:

assembler.c

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

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

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

甚至只需删除al处的include。不好的做法,因为编译器(没有函数信息)会认为它的返回值是一个整数,可能会引起其他警告。