代码之家  ›  专栏  ›  技术社区  ›  Leif Andersen

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

  •  15
  • Leif Andersen  · 技术社区  · 16 年前

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

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

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

    1. 这很常见吗?我不经常看到。使用这个准则是个好主意,还是应该直接开始定义代码。

    2. 例子是什么?为什么不举个例子,或者只是举个例子?这有什么特别的地方吗,或者只是Eclipse喜欢自动构建项目的人工制品?

    8 回复  |  直到 10 年前
        1
  •  14
  •   user308405    16 年前

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

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

    有些编译器允许“pragma once”执行相同的操作,但是“ifndef”构造在任何地方都有效。

        2
  •  4
  •   Jeff    16 年前

    这只是保护include的一种常见方法-这样可以防止代码被包含两次。所使用的标识符可以是任何东西,按照描述的方式来做只是惯例。

        3
  •  4
  •   anon    16 年前

    常见吗?是的- 全部的 C和C++头文件应该是这样构造的。示例_h是头保护,它防止头中的代码在同一翻译单元中包含多次,这将导致多个定义错误。名称exapmle_h被选择来匹配它正在保护的头文件的名称-它需要在您的项目中是唯一的,也可能是全局的。为了确保这一点,在项目名称前加前缀或后缀是正常的:

    #define MYPROJ_EXAMPLE_H
    

    例如,如果您的项目被称为“myproj”。别以为用下划线前缀会神奇地使它独一无二,顺便说一句,名字就像 _EXAMPLE_H_ 和 __EXAMPLE_H__ 是非法的,因为它们是为语言实现保留的。

        4
  •  2
  •   Jonathan M Davis    16 年前

    始终在头文件的顶部执行此操作。它通常被称为头罩或包括罩。

    它所做的是使其成为这样,如果一个头文件将包括多次,它将只包括一次。如果你不这样做,那么你最终会在被定义多次的事情和类似的事情上出错。

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

        5
  •  2
  •   James McNellis    16 年前

    这是一个包含警卫。它保证一个报头最多包含一次。

    例如,如果您要:

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

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

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

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

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

        6
  •  2
  •   corsiKa    16 年前

    考虑这个

    文件Fo.C:

    #include foo.h
    #include bar.h
    

    文件栏

    #include <iostream>
    #include foo.h
    

    现在,当我们编译foo.c时,有两次foo.h!我们当然不想这样做,因为所有的函数都会在第二次出现编译错误。

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

    这是很常见的(通常是强制的),如果有人不把一个放在那里,这是非常令人沮丧的。你 should 在包含时,可以简单地期望每个.h文件都有一个头保护。当然,你知道他们说什么,当你假设的事情(“使你和我的屁股”),但这应该是你期待看到的东西。

        7
  •  1
  •   Rashid Mirza    13 年前

    u人的意思是我必须为我要包含的每个头文件设置头保护。 我,E。我有以下头文件包括abc.h和def.h,而我必须放置头保护,如下所示 γ干扰素 #定义ABC和 γ干扰素 定义定义

        8
  •  0
  •   Christopher Barber    16 年前

    这被称为“包含保护”,实际上是C/C++头文件常见的习惯用法。这允许头文件被包括多次,而不包括其内容的乘法。

    名称示例_h_uuu是一种任意约定,但必须遵守C预处理器宏的命名规则,其中不包括例如example.h这样的名称。由于C宏都是在单个全局命名空间中定义的,因此不要有使用相同名称作为其include guard的不同头文件,这一点很重要。因此,最好将项目或库的名称包含在include guard名称中:

    #ifndef __MYPROJECT_EXAMPLE_H__
    ...