在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,还是只是示例?有没有什么特别之处,或者可能仅仅是eclipse如何更喜欢自动构建项目的工件?
答案 0 :(得分:14)
这是一个常见的结构。目的是仅在翻译单元中包含头文件的内容一次,即使物理头文件被包含多次也是如此。例如,如果您直接在源文件中包含标头,并且它也通过另一个标头间接包含,则会发生这种情况。
将#ifndef包装器放在内容周围意味着编译器只解析头部的内容一次,并避免重新定义错误。
有些编译器允许“#pragma once”执行相同的操作,但#ifndef构造可以在任何地方使用。
答案 1 :(得分:4)
这只是保护您的包含的常用方法 - 这样可以防止代码被包含两次。并且使用的标识符可以是任何东西,按照惯例,按照惯例进行操作。
答案 2 :(得分:4)
这是常见的吗?是 - 所有 C和C ++头文件应该像这样构造。 EXAMPLE_H是标题保护,它防止标题中的代码在同一个翻译单元中被多次包含,这将导致多个定义错误。选择名称EXAPMLE_H以匹配它所守护的头文件的名称 - 它需要在您的项目中是唯一的,也可能是全局的。为了确保这一点,在项目名称前加上或加上后缀是正常的:
#define MYPROJ_EXAMPLE_H
例如,如果您的项目名为“myproj”。不要试图用下划线作为前缀会神奇地使它成为唯一的 - 顺便说一下 - 像_EXAMPLE_H_
和__EXAMPLE_H__
之类的名称是非法的,因为它们是为语言实现保留的。
答案 3 :(得分:2)
始终在头文件的顶部执行此操作。它通常被称为头部防守或包含防守。
它的作用是使得如果多次包含头文件,它将只包含一次。如果你不这样做,那么你最终会得到关于多次定义事物的错误以及类似的事情。
确切的定义并不重要,尽管通常它是文件名的一些变体。基本上,您正在检查是否已定义给定的宏。如果没有,则定义它,然后继续包含该文件。如果有,则必须先包含该文件,并忽略该文件的其余部分。
答案 4 :(得分:2)
这是一名包括警卫。它保证包含的标题不超过一次。
例如,如果您要:
#include "example.h"
#include "example.h"
第一次包含标题时,将不会定义EXAMPLE_H_
并输入if-block。然后EXAMPLE_H_
指令定义#define
,并评估标题的内容。
第二次包含标题时,EXAMPLE_H_
已经定义,因此不会重新输入if-block。
这对于确保您不违反单一定义规则至关重要。如果在标头中定义一个没有包含保护并且包含该标题两次的类,则由于违反了一个定义规则而导致编译错误(该类将被定义两次)。
虽然上面的示例很简单,但您可以很容易地看到包含example.h
两次,但是频繁的标题包含其他标题,而且不是那么明显。
答案 5 :(得分:2)
考虑一下
文件foo.c:
#include foo.h
#include bar.h
文件bar.h
#include <iostream>
#include foo.h
现在,当我们编译foo.c时,我们在那里有两次foo.h!我们绝对不希望这样,因为所有函数都会在第二次抛出编译错误。
为防止这种情况发生,我们将INCLUDE GUARD
置于顶部。这样,如果已经包含它,我们定义一个预处理器变量,告诉我们不要再包含它。
这是非常常见的(通常是强制性的),如果有人不在那里,那就非常令人沮丧。您should
能够简单地期望每个.h文件在您包含时都有一个标题保护。当然,你知道他们在你做某些事情时会说些什么(“捏造你和我的屁股”),但那应该是你期待看到的东西。
答案 6 :(得分:1)
U人意味着我必须为每个我想要包含的头文件放置标题 我,e ..我有以下头文件,包括abc.h和def.h,而不是我必须把头保护如下 #ifndef abc_h #define abc_h和 #ifndef def_h #define def_h
答案 7 :(得分:0)
这被称为“包含守卫”,并且确实是C / C ++头文件的常用习惯用法。这允许头文件被多次包含而不包括其内容。
名称EXAMPLE_H_是一个任意约定,但必须遵守C预处理器宏的命名规则,这些宏排除了像example.h这样的名称。由于C宏都是在单个全局命名空间中定义的,因此重要的是您没有不同的头文件,这些头文件使用相同的名称作为其包含保护。因此,通常最好在包含保护名称中包含项目或库的名称:
#ifndef __MYPROJECT_EXAMPLE_H__
...