多个定义和仅标头库

我有一个带有几个c和h文件的C程序。 我决定将程序的一部分设置为“仅限标题”,因此我将代码从c移到了h。 现在我得到了多重定义问题,我不明白为什么。 例如:

main.c includes utils.h vector.c includes utils.h 

我将utils.c中的所有内容移动到utils.h(当然从项目中删除了utils.c)。 utils.h以。开头

 #ifndef UTILS_H_ #define UTILS_H_ // and end with: #endif 

为了确保我的警卫是独一无二的,我尝试改变它(例如:UTILS718171_H_),但它不起作用。

仍然,编译器抱怨:

 /tmp/ccOE6i1l.o: In function `compare_int': ivector.c:(.text+0x0): multiple definition of `compare_int' /tmp/ccwjCVGi.o:main.c:(.text+0x660): first defined here /tmp/ccOE6i1l.o: In function `compare_int2': ivector.c:(.text+0x20): multiple definition of `compare_int2' /tmp/ccwjCVGi.o:main.c:(.text+0x6e0): first defined here /tmp/ccOE6i1l.o: In function `matrix_alloc': ivector.c:(.text+0x40): multiple definition of `matrix_alloc' /tmp/ccwjCVGi.o:main.c:(.text+0x0): first defined here ... 

问题可能是这样的:所有c文件都被编译并获得自己的代码版本,然后在链接时会导致问题,但我老实说不知道如何解决这个问题。

如果在头文件中定义变量并将头包含在多个c文件中,则必然会出现多个定义错误,因为您违反了One定义规则(ODR) ,该规则指出一个转换单元中应该只有一个定义(头文件+源文件)。

解决方案是:
您应该只定义一次获得多个定义错误的实体。
对于function:
在头文件(包含在其他源文件中)中声明函数原型,并在一个且仅一个源文件中定义该函数。
对于全局变量:
在头文件中声明变量extern(包含在其他源文件中),然后在一个且仅一个源文件中定义变量。

你错过了#ifndef _FOO_H / #define _FOO_H / #endif构造的观点。 这只能防止一个文件中的多个包含。 例如,他们防止这种情况:

foo.h中:

  #ifndef _FOO_H #define _FOO_H /* some C stuff here */ #endif /* _FOO_H */ 

foo.c的:

  #include  #include  ... 

bar.h:

  #include  ... 

注意foo.c和bar.h都包含foo.h; 这里#ifdef _FOO_H / #define _FOO_H / #endif保护foo.c中的双重包含(bar.h中包含的foo.h不重新定义东西)

现在是下一部分。

为什么要将函数实现从utils.c移动到utils.h? 另外你为什么决定让它“仅限标题”?

您可以根据编译器是否支持static inline函数执行此操作; 但即便如此,也不建议这样做,因为很可能会使你的程序不必要地膨胀,因为你的util函数非常复杂,无论如何也无法内联。

因此,将其更改回您之前拥有的utils.c和utils.h构造,我认为,WAS正在工作并享受该软件。

你违反了One-Definition-Rule。 每个函数必须精确定义一次 ,最后在每个翻译单元中定义它。

你根本做不到这样的事情:

 // header.h void foo() { } // file1.c #include "header.h" // file2.c #include "header.h" 

唯一真正的解决方案是声明 void foo(); 在标题中并仅定义一次(通常在专用的foo.c )。 全局变量也是如此,它应该在标题中声明为extern并在源文件中定义。

包括警卫与此无关。 它们仅用于防止递归自包含或在一个翻译单元内冗余多重包含。

如果您将utils.h函数的“ utils.h ”复制到每个使用它的地方,只需在标题中使用static函数。 (C99中的static inline