9

我目前正在准备 CS 课程的期末考试,我遇到了一个关于 C++ #ifndef 语法的小问题(也许是大问题?)。

在将 #infndef 用作 #include 保护时,我已经查看了它的语法,并且网络上的大多数似乎都说:

#ifndef HEADER_H
#define "header.h"
...
#endif

但是我班的教程幻灯片显示的示例如下:

#ifndef __HEADER_H__
#define "header.h"
...
#endif

我想知道两者之间的区别是什么(如果有的话)。考试很可能会要求我写一个#include 守卫,我知道传统的智慧就是按照教授/导师所说的去做,但是如果在编译过程中存在差异,我想知道。

4

4 回答 4

18

通常的做法是两者都不做,并将包含保护放在头文件中,因为它减少了重复。例如:

头文件.h

#ifndef HEADER_H
#define HEADER_H

// Rest of header file contents go here

#endif

确切地说,您用作宏名称的内容取决于您的特定编码标准。但是,C 和 C++ 标准中有各种微妙的规则阻止您使用以下划线1开头的标识符,因此您应该避免使用__HEADER_H__,只是为了安全起见。

还值得一提的是,您应该选择不太可能与代码库中的任何其他内容发生冲突的内容。例如,如果您碰巧有一个HEADER_H在其他地方调用的变量(我意识到这不太可能),那么您最终会遇到一些令人愤怒的错误。


1. 参见例如 C99 标准的第 7.1.3 节。

于 2012-04-09T17:21:36.477 回答
5

以双下划线开头的名称是为实现保留的,所以我建议不要__SOMETHING在你的包含保护中使用。此外,尝试选择不太可能发生冲突的名称。所以看来你们班的教程至少在两个方面是错误的。例如,请参阅这篇幽默文章

于 2012-04-09T17:25:58.347 回答
1

如果您不在其他任何地方的变量名中使用下划线,则没有区别,这只是一种命名约定。

你只需要放一些独特的东西。

于 2012-04-09T17:23:20.950 回答
1

将包含保护放在包含头文件的文件中而不是头文件本身的一个论点是,如果文件已经被包含,则编译器(特别是预处理器)不必再次打开并读取包含文件.

这是一个软弱的论点。在实践中,节省的时间是微不足道的,而且出错的可能性很大。

在您的示例中:

#ifndef HEADER_H
#include "header.h"
...
#endif

你没有向我们展示#define HEADER_H. 它在某处header.h吗?如果是这样,你怎么知道作者header.h选择使用HEADER_H作为包含保护宏的名称?如果它稍后更改为其他内容怎么办?

如果您决定将包含保护放在包含文件中,您也应该在其中定义宏:

#ifndef HEADER_H
#include "header.h"
#define HEADER_H
#endif

但是,正如其他答案已经说过的那样,将守卫放在标题本身要好得多:

标头.h:

#ifndef HEADER_H
#define HEADER_H
/* contents of header.h */
#endif

然后包含简单地有:

#include "header.h"

并且少了一条需要担心的信息。

于 2012-04-09T17:35:47.057 回答