2010-05-11 92 views
14

在eclipse中,无论何时创建一个新的C++类或头文件,我都会得到以下类型的结构。说我创建的头文件example.h文件,我得到这个:针对C/C++代码的预处理指令#ifndef

/*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,或者仅仅是例子?有没有什么特别的,或者可能只是一个人工制品如何偏爱自动构建项目?

+0

注意,一切都在IFNDEF与ENDIF之间,在任何情况下,你作为一个应用程序员很可能会遇到。所以并不仅仅是#define被定义和包含一次,而是一切只被定义和包含一次。 – 2010-05-11 16:25:52

+0

好点,抱歉没有更明确地表示,谢谢。 – 2010-05-11 19:17:25

回答

13

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

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

有些编译器允许“#pragma once”做同样的事情,但是#ifndef构造可以在任何地方工作。

+0

啊,好吧,所以你#define语句只是在那里来定义一些东西,我可以在两种情况下将EXAMPLE_H_替换为FOO_BAR_,它仍然可以工作,它只是更好使用EXAMPLE_H_,因为与命名空间冲突的可能性相比,如果我给它任何其他名称的话,它的可能性要小得多。 – 2010-05-11 16:04:54

+0

正确的是,人们通常使用带有下划线的标题名称作为标识符中无效的字符。使用可能冲突的常见名称击败目的:) – user308405 2010-05-11 16:07:11

+0

@Leif Andersen:像例子这样的常见名称可能会发生冲突。就我个人而言,我用全名命名空间加上文件名称,因为这不太可能发生冲突。我看到其他人生成完整的GUID以避免冲突的可能性。 – 2010-05-11 16:53:54

4

这只是保护您的包含的一种常见方式 - 以这种方式防止代码被包含两次。而且使用的标识符可以是任何东西,只是按照所述的方式进行约定。

2

请务必在头文件的顶部执行此操作。它通常被称为头球后卫或包括后卫。

它的作用是这样的,如果一个头文件将包含多次,它将只包含一次。如果你不这样做,那么你最终会遇到有关多次定义事情的错误以及类似的事情。

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

2

这是一名包括警卫。它保证包含标题不超过一次。

例如,如果你要:

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

第一次被包括在报头,EXAMPLE_H_不会被定义和将被输入的,如果块。 EXAMPLE_H_然后由#define指令定义,并对头的内容进行评估。

第二次包含标题时,EXAMPLE_H_已被定义,所以if块不会被重新输入。

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

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

+0

不,它不!它保证包含它不仅仅是一次:-) – Vicky 2010-05-11 16:00:13

4

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

#define MYPROJ_EXAMPLE_H 

例如,如果你的项目被称为“的Myproj”。不要试图认为带有下划线的前缀会奇迹般地使它变得独一无二,像_EXAMPLE_H___EXAMPLE_H__之类的名称是非法的,因为它们是为语言实现保留的。

0

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

名称EXAMPLE_H_是一个任意约定,但必须遵守C预处理器宏的命名规则,该规则不包括像example.h这样的名称。由于C宏全部在单个全局名称空间中定义,所以重要的是您没有不同的头文件,它们的包含守护程序使用相同的名称。因此,它通常是一个好主意,包括您在包括后卫名称项目或库的名称:

#ifndef __MYPROJECT_EXAMPLE_H__ 
... 
+3

除了以下划线开头的名字后跟一个大写字母或其他下划线被保留给实现(即,不要用下划线开始您的包含保护名称)。 – 2010-05-11 16:05:33

+0

@James以及任何包含连续两个下划线的标识符(即不只是在开始处)。换句话说,这个答案充满了违规。 ;) – 2010-05-11 16:24:21

2

考虑这个

foo.c文件:

#include foo.h 
#include bar.h 

文件吧.H

#include <iostream> 
#include foo.h 

现在,当我们编译foo.c的,我们有foo.h中在那里的两倍!我们绝对不想这样做,因为所有的函数都会在第二次抛出编译错误。

为了防止发生这种情况,我们将INCLUDE GUARD置于顶端。这样,如果它已经包含在内,我们定义一个预处理器变量,告诉我们不要再包含它。

这是非常普遍的(通常是强制性的),并且如果有人不把它放在那里非常沮丧。你should能够简单地期望每个.h文件有一个头后卫,当你包括在内。当然,你知道他们说什么,当你承担的事情(“让你和我屁股”),但这应该是你期待看到的东西。

1

U人的意思是我必须为每个头文件放置头文件,我想包括在内。 我,我..我有以下头文件包含abc.h和def。^ h比我将页眉后卫如下 的#ifndef abc_h 的#define abc_h和 的#ifndef def_h 的#define def_h