C头中的function?
我听说您将函数原型放在头文件中,然后将函数定义放在.c文件中。 但是,这个.c文件是什么。 例如,如果你要包含一个文件“foo.h”,你会调用前面提到的.c文件“foo.c”,把函数定义放在其中,把它放在与foo.h相同的地方,并且当你尝试包含foo.h时,该函数是否会从c文件中inheritance并且该函数是否可以使用?
不,只需将.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
未定义引用。
头文件只是传统的。 C预处理器正在处理#include
指令 ,并且编译器会看到预处理的输入(但是您可以复制并粘贴大量的C代码以获得等效的#include
)。 实际上,预处理器并不关心你是否#include "foo.h"
或#include "foo.c"
,但后者往往是品味不佳。 使用.h
后缀命名头文件只是一种(非常常见的) 约定 。
因此,如果您在多个源文件(技术上的翻译单元 )中包含的标题中有一个函数定义,那么该函数定义就在每个这样的翻译单元中。
然后发生什么取决于该函数定义(它应该是static
甚至更好的static inline
)。
实际上,您应该将标头中的函数定义限制为static
或static inline
。 如果你没有在一个包含在几个*.c
文件中的头文件中声明一个函数定义void foo(int x) { /* something */ }
,你将在链接时有多个foo
错误定义。 将函数定义放在标题中的主要兴趣是启用内联(因此inline
提示); 否则(通常的情况),你不需要它,你只需将函数原型放在头文件和函数定义中的一个 *.c
文件中。
如果你有简短的快速运行函数,最好将它们定义为static inline
(所以给它们的主体)在你的头文件中(当然,这会增加编译时间)。 否则,这是不值得的负担。
一些头文件可能有很长的宏(几十个物理行,除了最后以反斜杠结尾的所有物理行)扩展到函数定义。 查看sglib的示例。
请注意, inline
是今天(就像register
在过去十年中一样)只是对编译器的一个提示 (用于内联扩展优化),允许忽略它(同样,许多优化编译器能够内联函数而不需要任何注释,前提是它们知道被调用函数的主体)。
不要忘记启用所有警告和调试信息。 使用 GCC,可以使用gcc -Wall -Wextra -g
,也许使用-Wstrict-prototypes
。 您可以使用-H
(以及使用-C -E
的预处理表单)获取包含的文件。
有关详细信息,请参阅某些C 参考站点和C11标准n1570 。 阅读有关预处理的GNU cpp
参考手册。