为什么在C ++头文件中使用#ifndef和#define?


495

我通常在头文件的开头看到这样的代码:

#ifndef HEADERFILE_H
#define HEADERFILE_H

并且在文件末尾是

#endif

这样做的目的是什么?


36
+1-我也有同样的疑问,在这里得到的答案更多,可能对将来的访问者有用:stackoverflow.com/q/3246803/1134940
Abid Rahman K

6
我要补充一点,您也可以只使用一次#pragma,这就是您要做的全部,并且它的作用与ifndef相同。有关两者的比较,请参阅:stackoverflow.com/questions/1143936/…–
尺寸

3
最好说一下a #pragma是什么:它激活特定于编译器的功能。虽然#pragma once广泛的支持,这是非标准的。
Potatoswatter

3
@Dimension:GNU自己的文档(info cpp查看此处)说:“并不是所有预处理器都可以识别它,因此您不能在可移植程序中依赖它。” 并且GNU cpp优化了通用和可移植的#ifndef习惯用法,因此它的效率与一样#pragma once
基思·汤普森

3
需要考虑的一些事情:不要使用下划线开头的宏名称;此类标识符保留给实现。更巧妙地,#ifndef HEADERFILE_H可以违反实现的名称空间的标题名称恰好以E; 开头。以E,数字或大写字母开头的标识符保留给<errno.h>。我建议#ifndef H_HEADERFILE
基思·汤普森

Answers:


525

这些被称为#include后卫

包含标头后,它将检查是否定义了唯一值(在这种情况下为HEADERFILE_H)。然后,如果未定义,则定义它并继续到页面的其余部分。

当再次包含该代码时,第一个ifndef失败,从而导致文件空白。

这样可以防止对任何标识符(例如类型,枚举和静态变量)进行双重声明。


Koning Baard XIV:VC甚至都具有#pragma once相同的功能:-)
Joey

95
它还可以防止递归包含...想象一下“ alice.h”包括“ bob.h”,“ bob.h”包括“ alice.h”,并且其中没有警卫……
Kevin Dungs,2009年

@凯文:这就是我的意思。我想操作一个由表单打开的表单来进行操作。它给了我很多错误,我不知道该怎么办。我放弃了=)

6
@Јοеу:#pragma once不可移植;#ifndef建议使用常见的习惯用法。
基思·汤普森

2
@CIsForCookies将“一个定义规则”打入您喜欢的搜索引擎。
David Schwartz

33
#ifndef <token>
/* code */
#else
/* code to include if the token is defined */
#endif

#ifndef检查给定令牌是#defined在文件中还是包含在文件中的较早版本;如果没有,它包括它和关闭之间的代码#else,或者如果没有#else存在,#endif语句。#ifndef通常,通过在包含文件后定义令牌并检查未在该文件的顶部设置令牌来定义头文件,从而使头文件成为幂等。

#ifndef _INCL_GUARD
#define _INCL_GUARD
#endif

4
以下划线开头的标识符被保留;您不应该自己定义它们。使用类似的东西#ifndef H_HEADER_NAME
基思·汤普森

5
我知道这是一个旧注释,但实际上下划线限制仅适用于“外部标识符”-可能会出现在已编译对象的符号表中的标识符,即全局变量和函数名。它不适用于宏名称。
Stu 2014年

1
斯图的评论正确吗?我刚刚阅读了stackoverflow.com/questions/228783/…,但是现在我不太确定。
威尔

9

这样可以防止多次多次包含相同的头文件。

#ifndef __COMMON_H__
#define __COMMON_H__
//header file content
#endif

假设您已将此头文件包含在多个文件中。因此,第一次未定义__COMMON_H__时,它将被定义并包含头文件。

下次定义__COMMON_H__时,将不再包含它。


1

它们被称为ifdef或包括警卫队。

如果编写一个小程序,似乎不需要它,但是随着项目的增长,您可能会有意或无意地多次包含一个文件,这可能导致编译警告,例如已声明的变量。

#ifndef checks whether HEADERFILE_H is not declared.
#define will declare HEADERFILE_H once #ifndef generates true.
#endif is to know the scope of #ifndef i.e end of #ifndef

如果未声明,则意味着#ifndef生成true,则仅执行#ifndef和#endif之间的部分,否则不执行。这将防止再次声明标识符,枚举,结构等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.