我有两个源文件:
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的重复符号?我只是在这里调用函数......不是吗?
答案 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 )。要解决此问题,请使用原型创建头文件:
void parse_file(char *config_file);
并包含那个文件:
#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。不好的做法,因为编译器(没有函数信息)会认为它的返回值是一个整数,可能会引起其他警告。