我听说您将函数原型放在头文件中,然后将函数定义放在.c文件中。但是,这个.c文件是什么。例如,如果您要包含一个文件" foo.h",您是否会调用前面提到的.c文件" foo.c",将函数定义放入其中,将其放入与foo.h相同的地方,当你尝试包含foo.h时,该函数是否会从c文件中继承并且该函数是否可以使用?
答案 0 :(得分:3)
不,只需将.c
与.h
放在一起并将其包含在您的代码中,就不会神奇地继承函数的定义。
您需要将foo.c
分别编译为目标文件(在Linux的情况下,它是.o
文件)。例如,使用命令 -
gcc -c foo.c -o foo.o
现在,foo.o
需要链接到您的实际程序。这可以通过在编译为
gcc test.c foo.o -o test.out
如果您没有将foo.o
与您的程序链接,您的链接器将无法找到其中定义的函数的实现,并将抛出链接器错误 -
对函数
foo_function
的未定义引用。
答案 1 :(得分:1)
头文件只是传统的。 C preprocessor正在处理#include
directive,并且编译器会看到预处理的输入(但您可以复制并粘贴大量的C代码以获得等效的#include
)。实际上,预处理器并不关心你是#include "foo.h"
还是#include "foo.c"
,而后者往往是不好的品味。命名带有.h
后缀的头文件只是(非常常见的)约定。
因此,如果您在多个源文件(技术上为translation unit s)中包含的标头中有一个函数定义,那么该函数定义就在每个这样的翻译单元中。
然后发生什么取决于该功能定义(它应该是static
或更好static inline
)。
实际上,您应该将标题中的函数定义限制为static
或static inline
。如果您未在多个static
文件中包含的标头中声明void foo(int x) { /* something */ }
函数定义*.c
,则foo
错误的多个定义位于inline
3}}时间。将函数定义放在标题中的主要兴趣是启用内联(因此*.c
提示);否则(通常的情况),你不需要它,你只需将函数原型放在头文件中,并将函数定义放在static inline
文件的一个中。
如果你有简短的快速运行功能,那么将定义它们作为inline
(所以给它们的身体)在你的头文件中是明智的(当然,这会增加编译时间)。否则,这不值得担负。
某些头文件可能有很长的宏(几十个物理行,除了最后以反斜杠结尾的所有物理行)都扩展为函数定义。查看link的示例。
请注意,register
今天(就像gcc -Wall -Wextra -g
在过去十年中一样)只是编译器的提示(用于sglib优化),这是允许忽略它(同样,许多inline expansion能够在没有任何注释的情况下内联函数,只要它们知道被调用函数的主体)。
不要忘记启用所有警告和调试信息。 optimizing compilers GCC,使用-Wstrict-prototypes
,也许使用-H
。您可以使用-C -E
(以及带有url = "https://www.sixt.ie/php/reservation/offerselect"
的预处理表单)获取包含的文件。