繁体   English   中英

C/C++ 代码的预处理器指令 #ifndef

[英]Preprocessor directive #ifndef for C/C++ code

在 Eclipse 中,每当我创建一个新的 C++ 类或C头文件时,我都会得到以下类型的结构。 假设我创建了头文件 example.h,我得到了这个:

/*Comments*/
#ifndef EXAMPLE_H_
#define EXAMPLE_H_
/* Place to put all of my definitions etc. */
#endif

我认为 ifndef 是说如果没有定义EXAMPLE_H_,请定义它,这可能有用,具体取决于您使用什么工具来编译和链接您的项目。 但是,我有两个问题:

  1. 这是相当普遍的吗? 我不经常看到它。 使用该标题是个好主意,还是应该直接跳到定义代码中。

  2. 什么是EXAMPLE_H_? 为什么不是example.h,或者只是example? 有什么特别之处吗,或者可能只是 eclipse 喜欢自动构建项目的工件?

这是一个常见的构造。 目的是在翻译单元中只包含一次头文件的内容,即使物理头文件被包含多次。 例如,如果您将标头直接包含在源文件中,并且它也通过另一个标头间接包含,则可能会发生这种情况。

将#ifndef 包装器放在内容周围意味着编译器只解析头的内容一次,并避免重新定义错误。

一些编译器允许“#pragma once”做同样的事情,但#ifndef 结构在任何地方都有效。

这只是保护包含的常用方法 - 通过这种方式可以防止代码被包含两次。 使用的标识符可以是任何东西,按照所描述的方式进行操作只是约定俗成的。

常见吗? 是的 -所有C 和 C++ 头文件都应该像这样构造。 EXAMPLE_H 是一个头文件保护,它防止头文件中的代码在同一个翻译单元中被多次包含,这会导致多个定义错误。 选择名称 EXAPMLE_H 以匹配它所保护的头文件的名称 - 它需要在您的项目中是唯一的,也可能是全局的。 为了确保这一点,使用您的项目名称作为前缀或后缀是正常的:

#define MYPROJ_EXAMPLE_H

例如,如果您的项目名为“myproj”。 顺便说一下,不要认为加下划线的前缀会神奇地使它独一无二 - 像_EXAMPLE_H___EXAMPLE_H__这样的名称是非法的,因为它们是为语言实现保留的。

始终在头文件的顶部执行此操作。 它通常称为标题保护或包含保护。

它的作用是使得如果一个头文件被多次包含,它只会被包含一次。 如果你不这样做,那么你最终会遇到关于事物被多次定义的错误等等。

确切的定义并不那么重要,尽管通常它是文件名的一些变化。 基本上,您正在检查是否已定义给定的宏。 如果没有,则定义它,并继续包含该文件。 如果有,则您之前必须包含该文件,并且文件的其余部分将被忽略。

这是一个包含守卫。 它保证包含的标题不超过一次。

例如,如果您要:

#include "example.h"
#include "example.h"

第一次包含标题时, EXAMPLE_H_不会被定义并且会进入 if 块。 EXAMPLE_H_然后由#define指令定义,并评估标头的内容。

第二次包含标题时,已经定义了EXAMPLE_H_ ,因此不会重新输入if块。

这对于确保您不违反单一定义规则至关重要。 如果您在没有包含保护的头文件中定义一个类并包含该头文件两次,由于违反了一个定义规则(该类将被定义两次),您将得到编译错误。

虽然上面的例子很简单,你可以很容易地看到你包含了example.h两次,但头文件经常包含其他头文件,这并不那么明显。

考虑这个

文件 foo.c:

#include foo.h
#include bar.h

文件 bar.h

#include <iostream>
#include foo.h

现在,当我们编译 foo.c 时,我们有两次 foo.h! 我们绝对不希望这样,因为所有函数第二次都会抛出编译错误。

为了防止这种情况,我们将INCLUDE GUARD放在顶部。 这样,如果它已经被包含,我们定义一个预处理器变量来告诉我们不要再次包含它。

这是很常见的(通常是强制要求的),如果有人不把它放在那里,就会非常令人沮丧。 当您包含时,您should能够简单地期望每个 .h 文件都有一个标头保护。 当然,当你假设事情(“让你和我混为一谈”)时,你知道他们说什么,但这应该是你期望看到的。

U人的意思是我必须为每个头文件放置标题保护我想要包括我,e ..我有以下头文件包含abc.h和def.h而不是我必须将标题保护放在下面#ifndef abc_h #define abc_h和#ifndef def_h #define def_h

这称为include guard ,确实是 C/C++ 头文件的常用习惯用法。 这允许头文件被多次包含而不会多次包含其内容。

名称EXAMPLE_H_是一个任意约定,但必须遵守C 预处理器宏的命名规则,不包括example.h名称。 由于 C 宏都定义在单个全局命名空间中,因此不要让不同的头文件对其包含保护使用相同的名称,这一点很重要。 因此,在包含保护名称中包含您的项目或库的名称通常是一个好主意:

#ifndef __MYPROJECT_EXAMPLE_H__
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM