我目前正在攻读CS课程的期末考试,我遇到了一个关于C ++ #ifndef语法的小问题(可能是主要的?)。
我在查看#infndef的语法时将其用作#include后卫,网上的大多数人都说:
#ifndef HEADER_H
#define "header.h"
...
#endif
但我班级的教程幻灯片将示例显示为:
#ifndef __HEADER_H__
#define "header.h"
...
#endif
我想知道两者之间的差异(如果有的话)。考试很可能会让我写一个#include后卫,而且我知道传统的智慧只是与教授/导师说的一致,但如果在编译过程中存在差异,我想知道。
答案 0 :(得分:17)
通常的做法是不要这样做,并将包含守护放在头文件中,因为它可以减少重复次数。 e.g:
<强> header.h 强>
#ifndef HEADER_H
#define HEADER_H
// Rest of header file contents go here
#endif
您使用的宏名称恰好取决于您的特定编码标准。但是,C和C ++标准中有各种微妙的规则阻止您使用以下划线开头的标识符 1 ,因此您应该避免__HEADER_H__
,只是为了安全起见。 / p>
还值得一提的是,你应该选择一些不太可能与你的代码库中的任何其他东西冲突的东西。例如,如果你碰巧在其他地方有一个名为HEADER_H
的变量(不太可能,我意识到),那么你最终会遇到一些令人愤怒的错误。
<子> 1。参见例如C99标准第7.1.3节。
答案 1 :(得分:5)
以双下划线开头的名称是为实现保留的,因此我建议不要在include guard中使用__SOMETHING
。此外,尝试选择不太可能发生冲突的名称。所以看来你的班级教程至少有两个错误。例如,见humorous article。
答案 2 :(得分:1)
如果你不在其他任何地方使用变量名中的下划线没有区别,那只是一个命名约定。
你只需要放一些独特的东西。
答案 3 :(得分:0)
将包含保护包含在包含头文件而不是头文件本身的文件中的一个参数是,如果文件已被包含,则编译器(特别是预处理器)不必打开并读取再次包含文件。
这是一个微弱的论点。在实践中,节省的时间是微不足道的,并且错误的可能性很大。
在你的例子中:
#ifndef HEADER_H
#include "header.h"
...
#endif
您没有向我们展示#define HEADER_H
。它在header.h
的某个地方吗?如果是这样,您如何知道header.h
的作者选择使用HEADER_H
作为包含保护宏的名称?如果以后更改为其他内容怎么办?
如果你决定将include guard放在包含文件中,你也应该在那里定义宏:
#ifndef HEADER_H
#include "header.h"
#define HEADER_H
#endif
但是,正如其他答案已经说过的那样,将警卫放在标题中会好得多:
header.h:
#ifndef HEADER_H
#define HEADER_H
/* contents of header.h */
#endif
然后包含简单地:
#include "header.h"
并且需要担心的信息少一些。