需要澄清#ifndef #define
Need clarification on #ifndef #define
我正在使用的代码有多个不同 类 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.hh
或 cell.hh
文件?
更好的问题:写 __CELL_H_INCLUDED__
和 cellINCLUDED
一样吗?
预处理器定义没有特殊含义。唯一的要求是它们在模块中保持唯一,这就是为什么文件名通常是它们的一部分。
特别是,防止双重包含的机制不是 "baked in" 语言,而只是使用预处理器的机制。
话虽这么说,现在每个值得关注的编译器都支持 #pragma once
,您可能会接受它。
正如您引用的 link 所说,"compilers do not have brains of their own" - 所以要回答您的问题,不,编译不了解涉及哪些特定文件。它甚至不会理解“__cellINCLUDED”在概念上与特定文件有任何关系。
相反,include guard 简单地防止包含在其开始 #ifndef 和结束 #endif 之间的逻辑被多次包含。 你,作为程序员,告诉编译器不要多次包含该代码 - 编译器不会自己做任何事情'intelligent'。
不,这实际上是在告诉 compiler/parser 如果已经将其放入程序中,则不要将其加载。
这应该位于 .h 文件的顶部(底部有一个 #endif)。
假设您有 mainProgram.cpp 和 Tools.cpp,每个文件都加载 fileReader.h。
当编译器编译 each 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 位并在第二次忽略该代码。
这减少了编译时间,也意味着如果您使用的是 poor/old 编译器,它不会尝试再次插入代码。
#ifndef __MYCLASS_H_INCLUDED__
#define __MYCLASS_H_INCLUDED__
So in above code that I am working on, does compiler automatically
understands it is looking for face.hh or cell.hh files?
不,编译器不会自动理解你的意思。
真正发生的是,在编译 translation unit 时,编译器持有一个全局定义的宏列表。因此,您正在做的是定义 MACRO __MYCLASS_H_INCLUDED__
(如果它尚不存在)。
如果定义了那个宏,#ifndef
直到 #endif
将不会被实际的编译器解析。
因此,您可以测试该宏的存在,以确定编译器是否已解析该头文件以将其包含在翻译单元中一次且仅一次...这是因为编译器将每个翻译单元编译为 one flattened file (after merging all the #includes
)
见https://en.wikipedia.org/wiki/Include_guard
Is writing __CELL_H_INCLUDED__
same as cellINCLUDED
?
是的......有些人更喜欢使用带下划线前缀和后缀的 MACRO 来作为包含守卫的原因是因为它们被用作标识符的可能性极低......但同样,underscore could clash with the compiler。 ..
我更喜欢这样的东西:CELL_H_INCLUDED
如果您使用 cellINCLUDED
,有可能某天有人会使用它作为该翻译单元中的标识符
我正在使用的代码有多个不同 类 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.hh
或 cell.hh
文件?
更好的问题:写 __CELL_H_INCLUDED__
和 cellINCLUDED
一样吗?
预处理器定义没有特殊含义。唯一的要求是它们在模块中保持唯一,这就是为什么文件名通常是它们的一部分。
特别是,防止双重包含的机制不是 "baked in" 语言,而只是使用预处理器的机制。
话虽这么说,现在每个值得关注的编译器都支持 #pragma once
,您可能会接受它。
正如您引用的 link 所说,"compilers do not have brains of their own" - 所以要回答您的问题,不,编译不了解涉及哪些特定文件。它甚至不会理解“__cellINCLUDED”在概念上与特定文件有任何关系。
相反,include guard 简单地防止包含在其开始 #ifndef 和结束 #endif 之间的逻辑被多次包含。 你,作为程序员,告诉编译器不要多次包含该代码 - 编译器不会自己做任何事情'intelligent'。
不,这实际上是在告诉 compiler/parser 如果已经将其放入程序中,则不要将其加载。
这应该位于 .h 文件的顶部(底部有一个 #endif)。
假设您有 mainProgram.cpp 和 Tools.cpp,每个文件都加载 fileReader.h。 当编译器编译 each 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 位并在第二次忽略该代码。
这减少了编译时间,也意味着如果您使用的是 poor/old 编译器,它不会尝试再次插入代码。
#ifndef __MYCLASS_H_INCLUDED__ #define __MYCLASS_H_INCLUDED__
So in above code that I am working on, does compiler automatically understands it is looking for face.hh or cell.hh files?
不,编译器不会自动理解你的意思。
真正发生的是,在编译 translation unit 时,编译器持有一个全局定义的宏列表。因此,您正在做的是定义 MACRO __MYCLASS_H_INCLUDED__
(如果它尚不存在)。
如果定义了那个宏,#ifndef
直到 #endif
将不会被实际的编译器解析。
因此,您可以测试该宏的存在,以确定编译器是否已解析该头文件以将其包含在翻译单元中一次且仅一次...这是因为编译器将每个翻译单元编译为 one flattened file (after merging all the #includes
)
见https://en.wikipedia.org/wiki/Include_guard
Is writing
__CELL_H_INCLUDED__
same ascellINCLUDED
?
是的......有些人更喜欢使用带下划线前缀和后缀的 MACRO 来作为包含守卫的原因是因为它们被用作标识符的可能性极低......但同样,underscore could clash with the compiler。 ..
我更喜欢这样的东西:CELL_H_INCLUDED
如果您使用 cellINCLUDED
,有可能某天有人会使用它作为该翻译单元中的标识符