Need clarification on #ifndef #define

时间:2016-04-25 09:14:17

标签: c++ include-guards

The code I am working has multiple headers and source files for different classes face.cc, face.hh, cell.cc, cell.hh edge.cc edge.hh and the headers contain includes like this,

#ifndef cellINCLUDED
#define cellINCLUDED

#ifndef faceINCLUDED
#define faceINCLUDED

I saw through http://www.cplusplus.com/forum/articles/10627/ and saw the way to write include guard is

#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?

better question : Is writing __CELL_H_INCLUDED__ same as cellINCLUDED ?

4 个答案:

答案 0 :(得分:2)

#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?

No, the compiler doesn't automatically understand what you mean.

What really happens is that, when compiling a translation unit, the Compiler holds a list of globally defined MACROs. And so, what you are doing is defining the MACRO __MYCLASS_H_INCLUDED__ if it doesn't already exists.

If that macro is defined, that #ifndef until #endif will not be parsed by the actual compiler. Hence you can test for the existence of that MACRO to determine if the Compiler has parsed that header file to include it once and only once in the translation unit... This is because the compiler compiles each translation unit as one flattened file (after merging all the #includes)

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

Is writing __CELL_H_INCLUDED__ same as cellINCLUDED ?

Yes it is.... The reason some prefer using underscored prefixed and suffixed MACROs for include guards is because they have extremely low probability of ever being used as identifiers... but again, underscore could clash with the compiler...

I prefer something like this: CELL_H_INCLUDED

If you use cellINCLUDED, there are chances that someday, somebody may use it as an identifier in that translation unit

答案 1 :(得分:1)

The preprocessor definitions have no special meaning. The only requirement is that they stay unique across the modules, and that's why the file name is typically a part of them.

In particular, the mechanics for preventing double inclusion aren't "baked in" the language and simply use the mechanics of the preprocessor.

That being said, every compiler worth attention nowadays supports #pragma once, and you could probably settle on that.

答案 2 :(得分:0)

As the link you have referenced says, "compilers do not have brains of their own" - so to answer your question, no, the compile does not understand which particular files are involved. It would not even understand that '__cellINCLUDED' has anything conceptually to do with a specific file.

Instead, the include guard simply prevents the logic contained between its opening #ifndef and closing #endif from being included multiple times. You, as the programmer, are telling the compiler not to include that code multiple times - the compiler is not doing anything 'intelligent' on its own.

答案 3 :(得分:0)

Nope, This is essentially telling the compiler/parser that if this has already been put into the program, don't puthave already been loaded.

This should be at the top (and have an #endif at the bottom) of your .h file.

Lets say you have mainProgram.cpp and Tools.cpp, with each of these files loading fileReader.h. As the compiler compiles each cpp file it will attempt to load the fileReader.h. unless you tell it not to it will load all of the fileReader file in twice.

ifndef = if not defined

so when you use these (and the #endif AFTER all your code in the .h file) you are saying:

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

so this way when it goes to load the code in your .h file a second time it hits the if not defined bit and ignores the code on the second time.

This reduces compile time and also means if you are using a poor/old compiler it isn't trying to shove the code in again.