【问题标题】:Need clarification on #ifndef #define需要澄清#ifndef #define
【发布时间】:2016-04-25 09:14:17
【问题描述】:

我正在工作的代码有多个头文件和不同类的源文件face.cc, face.hh, cell.cc, cell.hh edge.cc edge.hh,头文件包含这样的内容,

#ifndef cellINCLUDED
#define cellINCLUDED

#ifndef faceINCLUDED
#define faceINCLUDED

我看透了http://www.cplusplus.com/forum/articles/10627/,看到include guard的写法是

#ifndef __MYCLASS_H_INCLUDED__
#define __MYCLASS_H_INCLUDED__

所以在我正在处理的上述代码中,编译器是否会自动理解它正在寻找face.hhcell.hh 文件?

更好的问题:写__CELL_H_INCLUDED__cellINCLUDED 一样吗?

【问题讨论】:

  • 不清楚宏定义与您的问题有什么关系。宏用于避免两次包含相同的标头(现在已弃用,取而代之的是 #pragma once)。请说明您想了解的内容。
  • 对不起。我的问题很基本。我只是在阅读这篇文章,因此我对 cellINCLUDED 是否与 _CELL_H_INCLUDED_ 工作方式相同感到困惑
  • 是的。唯一的要求是宏是唯一的。我会说推荐的系统更好。
  • 不要使用双下划线。 stackoverflow.com/questions/228783/…

标签: c++ include-guards


【解决方案1】:
#ifndef __MYCLASS_H_INCLUDED__
#define __MYCLASS_H_INCLUDED__

所以在我正在处理的上述代码中,编译器会自动 了解它正在寻找 face.hh 或 cell.hh 文件吗?

不,编译器不会自动理解您的意思。

真正发生的是,在编译translation unit 时,编译器拥有一个全局定义的宏列表。因此,您正在做的是定义 MACRO __MYCLASS_H_INCLUDED__(如果它尚不存在)。

如果定义了该宏,则#ifndef 直到#endif 将不会被实际编译器解析。 因此,您可以测试该 MACRO 的存在以确定编译器是否已解析该头文件以将其包含在翻译单元中一次且仅一次...这是因为编译器将每个翻译单元编译为 one flattened file (after merging all the #includes)

https://en.wikipedia.org/wiki/Include_guard

__CELL_H_INCLUDED__cellINCLUDED 一样吗?

是的....有些人更喜欢使用带下划线的前缀和后缀 MACRO 作为包含防护的原因是因为它们被用作标识符的可能性极低...但同样,underscore could clash with the compiler...

我更喜欢这样的东西:CELL_H_INCLUDED

如果您使用cellINCLUDED,则有可能有一天,有人可能会将其用作该翻译单元中的标识符

【讨论】:

  • 您不应该更喜欢使用下划线,尤其是前导下划线(后跟大写字母)和双下划线,因为它们是为实现而保留的。如果您想要一个极不可能用作标识符的宏,请将 GUID 附加到它。或者,如果您无法轻松访问 GUID 生成器,请将日期和时间附加到它。你不必记住它。
  • 嘿@WhiZTiM 感谢您的详细描述。我发现我对宏的理解存在漏洞,现在我知道得更多了 :) 而且我还没有阅读您链接的关于包含保护的维基百科文章。这也很有帮助。再次感谢:)
【解决方案2】:

预处理器定义没有特殊含义。唯一的要求是它们在模块中保持唯一,这就是为什么文件名通常是它们的一部分。

特别是,防止双重包含的机制并未“嵌入”语言中,而是简单地使用了预处理器的机制。

话虽如此,现在每个值得关注的编译器都支持#pragma once,你可能会选择它。

【讨论】:

    【解决方案3】:

    正如您引用的链接所说,“编译器没有自己的大脑” - 所以回答您的问题,不,编译不了解涉及哪些特定文件。它甚至不会理解“__cellINCLUDED”在概念上与特定文件有任何关系。

    相反,包含保护只是防止包含在其打开 #ifndef 和关闭 #endif 之间的逻辑被包含多次。 ,作为程序员,告诉编译器不要多次包含该代码 - 编译器本身并没有做任何“智能”的事情。

    【讨论】:

      【解决方案4】:

      不,这本质上是在告诉编译器/解析器,如果它已经被放入程序中,不要把它已经加载。

      这应该在您的 .h 文件的顶部(并且在底部有一个 #endif)。

      假设您有 mainProgram.cpp 和 Tools.cpp,每个文件都加载 fileReader.h。 当编译器编译 每个 cpp 文件时,它会尝试加载 fileReader.h。除非您告诉它不要,否则它将两次加载所有 fileReader 文件。

      ifndef = 如果未定义

      所以当你使用这些时(以及 .h 文件中所有代码之后的#endif) 你是说:

      if not defined: cellINCLUDED
      then define: cellINCLUDED with the following code:
      [code]
      end of code
      

      这样,当它第二次加载 .h 文件中的代码时,它会遇到 if not defined 位并在第二次忽略代码。

      这减少了编译时间,也意味着如果您使用的是劣质/旧的编译器,它不会试图再次将代码推入。

      【讨论】:

        猜你喜欢
        • 2011-11-09
        • 2012-07-18
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2012-06-02
        • 2017-01-18
        • 2016-06-30
        • 1970-01-01
        相关资源
        最近更新 更多