为什么将源文件包含在其他源文件中不是一种好的做法?更好的方法是包含头文件。采用这种方式有哪些好处,反之又有哪些缺点呢?请原谅我的英语不好。
int a = 42;
...
file b.c
/* Example of bad code */
#include "a.c"
...
a.c
和b.c
并将它们链接起来时,您将会得到multiple definition
链接错误。附言:当我说一般情况时,我指的是有时包含源代码可能是有用的。但在这种情况下,为避免给读者带来困惑,我更喜欢将文件后缀重命名为.inc
或类似的其他名称。
#ifndef...#endif
进行保护,这样如果它们中定义了符号,则在包含在多个文件中时不会产生链接器错误。在头文件中声明符号有时很有用,但应该避免使用。
文件扩展名只是开发人员的信息,没有必要使用.h扩展名,非常著名的例子是像'iostream'这样没有扩展名的文件。 - riodoro1这些C语言源代码文件必须有定义。例如,如果您有一个函数int add(int, int)
用于将两个数字相加,则其定义应如下:
int add(int x, int y)
{
return x + y;
}
一个头文件包含一个原型,它帮助编译器在代码中调用该函数时调用此函数,它告诉编译器如何为函数创建堆栈帧、参数数量和类型以及返回类型。
如果您包含一个包含上面代码示例的c源文件,则需要两个add()
函数的定义,这是不可能的。
相反,您可以将原型添加到头文件中,如下所示:
int add(int x, int y);
然后包含头文件,这样add()
函数就会有一个单一的定义。
你可能会问自己,如果我在另一个c源文件中使用它而没有提供定义,该函数将如何工作?
答案是,只有在编译器将所有对象文件链接成最终二进制文件时才需要函数定义。
inline
函数或自动生成的 static
表。你不需要每次都将它们添加到你的实现文件中。 - too honest for this site#include
的文件都会被编译器视为其文本已替换相应的#include
指令。尽管不完全相关,您可以在此处找到更多信息here,请注意预处理器保护。inline
函数,它们实际上必须在头文件中定义。static
结构的例外,所有模块都必须提供它们。另一个例外可能是自动生成的文件,例如仅由单个模块使用的表格。这些也应该被#include
,但声明为static
。通常,对于这些文件,人们会使用不同的扩展名,例如.inc
而不是.h
。
#include
的文件。同时也要注意:实际上确实存在一些好的用例需要包含定义:例如,自动生成的表格,你想要保持static
。或者即使是普通的头文件也可以使用inline
函数。 - too honest for this sitestatic
并在多个位置包含源文件,则会创建该表的多个副本。这可能会非常浪费,特别是在您刚提到的嵌入式系统中。 - barak manos