在头文件和源文件中都加入 <stdbool.h>?

3

我还是C语言新手,有一个关于源文件和头文件的问题。我有一个像这样的头文件:

#ifndef MISC_H_
#define MISC_H_
#define BYTE 8

#include <stdbool.h>
#include <stdio.h>
#include "DataStruct.h"

bool S_areEqual(char *firstString, char *secondString); /* (1) */
bool S_randomDataStructureCheck(char *string, DataStruct *data); /* (2) */

#endif
  1. 函数参数中使用了bool,因此在源文件中也有。我需要在头文件和源文件中都加入#include <stdbool.h>吗?是否存在某些情况下需要,而某些情况下不需要?

  2. 如果另一个头文件中有一个用作函数参数的typedef,那么在头文件和源文件中都需要加入#include "DataStruct.h"吗?

这是什么标准?


1
在你的例子中,没有明显的理由为什么头文件包含<stdio.h>。它没有指定任何类型的引用。你确实需要<stdbool.h>"DataStruct.h"。另请参见《C语言头文件使用模式的好的文档参考是什么?》《我应该在头文件中使用#include吗?》 - Jonathan Leffler
是的,这里不太明显,但是<stdio.h>在源代码中函数本身的错误检查过程中被使用。 - ChrisMcJava
感谢 @JonathanLeffler - ChrisMcJava
2
你需要区分代码使用者必须的头文件和实现代码必须的头文件。客户端使用的头文件应该只包含代码使用者所需的头文件。实现功能的代码可能需要<stdio.h>,但它应该隐藏在源文件中,而不是包含在头文件中。头文件定义了接口。它应该是自包含的(因此需要包括<stdbool.h>"DataStruct.h");它应该是最小化的,不包含多余的头文件(所以没有<stdio.h>)! - Jonathan Leffler
2个回答

3
不需要在头文件和源文件(.c)中都包含。如果您已经在一个被源文件包括的头文件中包含了它,那么它也将对该源文件可用。当一些头文件依赖于其他头文件时,头文件的包含顺序可能很重要。有关更多详细信息,请参见此答案
另外,您会注意到以下行:
#ifndef MISC_H_
#define MISC_H_

这确保头文件只被包含一次。

更新

来自评论:

所以在源代码中,您只需包含其相应的头文件?

如果你的意思是,一个源文件应该包含它自己的头文件,那就要看情况而定。通常,文件应该包含它们需要的文件。

如果一个源文件需要一个头文件,但是该头文件不需要它自己的头文件,则应该将include放在源文件中而不是它的头文件中。一个原因是每个文件只包含它需要的文件,这样很容易知道依赖关系。另一个原因是它减少了变更的影响。

让我们看一个例子。假设你有foo.c和foo.h,foo.c需要foodep.h来编译,但foo.h不需要:

选项1:foo.h

#include "foodep.h"

现在想象一下,还有许多其他文件foo1.h、foo2.h、foo3.h等都包含foo.h。然后,对foodep.h的任何更改都会影响所有这些其他文件及其相关的头文件和源文件。

选项2:foo.c

#include "foodep.h"

现在,没有其他文件能看到foodep.h。对foodep.h的更改只影响foo.c。

通常,尝试应用与面向对象编程相同的实践-封装和最小化变更范围。


在源代码中,你只需要包含相应的头文件吗? - ChrisMcJava
1
是的,定义函数的源代码必须包含声明函数的头文件,就像使用函数的源代码包含头文件一样重要。头文件确保函数的定义和使用得到正确的协调。 - Jonathan Leffler

0
简单来说,你应该始终包含你的程序中使用的提供函数/别名/宏的头文件,至于是否实际需要包含它们,应该由编译器决定。这是因为每个头文件都在特定的宏条件下定义(使用 #ifdef - #endif 语句),如果您定义自己的头文件,则有必要这样做,以避免多次包含,从而避免痛苦的编译器错误。因此,我的建议是,如果您的程序中使用了 bool,则应该包含 stdbool.h,如果编译器已经在某个其他头文件的定义中包含了它,那么它将不会再次包含 stdbool。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接