[英]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_,请定义它,这可能有用,具体取决于您使用什么工具来编译和链接您的项目。 但是,我有两个问题:
这是相当普遍的吗? 我不经常看到它。 使用该标题是个好主意,还是应该直接跳到定义代码中。
什么是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.