用于C / C ++代码的预处理程序指令#ifndef

在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,还是只是示例? 有没有什么特别的,或者可能只是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-block。 然后,由#define指令定义EXAMPLE_H_ ,并评估头的内容。

第二次包含头时, EXAMPLE_H_已经定义,因此不会重新输入if-block。

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

虽然上面的示例很简单,但您可以很容易地看到包含example.h两次,通常标题包含其他标题,并且它不那么明显。

考虑一下

文件foo.c:

 #include foo.h #include bar.h 

文件bar.h

 #include  #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

这被称为“包含守卫”,并且确实是C / C ++头文件的常用习惯用法。 这允许头文件被多次包含而不包括其内容。

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

 #ifndef __MYPROJECT_EXAMPLE_H__ ...