ChatGPT解决这个技术问题 Extra ChatGPT

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

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

#ifndef HEADERFILE_H
#define HEADERFILE_H

在文件的末尾是

#endif

这样做的目的是什么?

+1 - 我也有同样的疑问,在这里得到了更好的答案,可能对未来的访问者有用:stackoverflow.com/q/3246803/1134940
我想补充一点,你也可以使用 #pragma once,这就是你所要做的,它的目的与 ifndef 相同。有关两者的比较,请参阅:stackoverflow.com/questions/1143936/…
最好提一下 #pragma 是什么:它激活特定于编译器的功能。尽管 #pragma once 得到了非常广泛的支持,但它是非标准的。
@Dimension:GNU 自己的文档(info cpplook here)说“并非所有预处理器都能识别它,因此您不能在可移植程序中依赖它。”。并且 GNU cpp 优化了通用和可移植的 #ifndef 习惯用法,因此它与 #pragma once 一样高效。
需要考虑的一些事项: 不要使用以下划线开头的宏名称;此类标识符保留给实现。更巧妙的是,#ifndef HEADERFILE_H 可以违反实现的命名空间,标题名称恰好以 E 开头;以 E 和数字或大写字母开头的标识符保留给 <errno.h>。我建议#ifndef H_HEADERFILE

P
Peter Mortensen

这些称为 #include guards

包含标头后,它会检查是否定义了唯一值(在本例中为 HEADERFILE_H)。然后,如果它没有定义,它会定义它并继续到页面的其余部分。

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

这可以防止重复声明任何标识符,例如类型、枚举和静态变量。


Koning Baard XIV: VC 甚至有一个 #pragma once 做同样的事情:-)
它还可以防止递归包含......想象一下“alice.h”包括“bob.h”和“bob.h”包括“alice.h”并且他们没有包括警卫......
@Јοеу:#pragma once 不可移植;建议使用常见的 #ifndef 成语。
@CIsForCookies 将“一个定义规则”打入您最喜欢的搜索引擎。
@JasonArg123:是的,但这并不总是一件坏事。 #pragma once 是明确的;它说“一旦我#include进入给定的翻译单元,就不要再打开这个文件了”。包含守卫说“如果我再次被包含,请跳过我的内容”(但文件仍然在逻辑上打开,从头到尾读取,并且守卫丢弃内容)。我没有检查最近的编译器,但是有一段时间,GCC 识别了包含保护习语并隐式地做了 #pragma once 所做的事情,而 MSVC 没有,所以如果你也没有 #pragma once,你会打开并重复处理文件,增加系统调用开销。
Q
QuantumFool
#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

保留以下划线开头的标识符;你不应该自己定义它们。使用类似 #ifndef H_HEADER_NAME 的内容。
我知道这是一条旧评论,但实际上下划线限制仅适用于“外部标识符”——最终可能出现在编译对象的符号表中的标识符,即全局变量和函数名。它不适用于宏名称。
斯图的评论是真的吗?我刚刚阅读了 stackoverflow.com/questions/228783/…,现在我不太确定。
不,尽管这是一种常见的做法,但用户在 C++ 的任何范围内定义以下划线开头的任何符号后跟大写字母都是未定义的行为。在实践中,此类符号可用于定义标准库中的宏,这可能与用户定义的相同形式的符号发生冲突(我期待 2023 年的回应;问候,从鼠疫时代开始!)例外:用户定义的文字。
S
Sandeep_black

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

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

假设您已将此头文件包含在多个文件中。所以第一次 __COMMON_H__ 没有定义,它将被定义并包含头文件。

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


M
Mohit Jain

它们被称为 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 之间的部分执行,否则不执行。这将防止再次声明标识符、枚举、结构等......