Reputation: 63
just a beginner question, what's going on with #ifndef SOME_HEADER_H
understandable that it is a preprocessor directive for conditional compilation, if some header is already included (i might be wrong correct me?) move on , if it's not, include
it, i read at some blog the letter sentence with these words instead, if it's defined move on else #define
it, well i thought we can just include a header file not define a header file , how can a header file be defined, and what's the relation here ? and the second question, the file name was foo.h
and when he try to check if it's defined he does #ifndef FOO_H #define FOO_H
, ok how foo.h
have been translated to FOO_H
, does the c mechanism know that he's talking about that specific file or does he done something before-word? thank's for your time!
Upvotes: 1
Views: 1190
Reputation: 117298
What you have here is a header guard:
File: some_header.h
#ifndef SOME_HEADER_H // if SOME_HEADER_H is not defined, enter the
// #ifndef ... #endif block
#define SOME_HEADER_H // and define SOME_HEADER_H
struct foo {
int x;
};
#endif
This protects the header from being included more than once in the same translation unit and thereby trying to define the same entities more than once. The macro SOME_HEADER_H
will stay defined until the translation unit is done so no matter how many times this header is included in the translation unit (implicitly via other header files) its contents will only be parsed once for that translation unit.
You can now do this:
File: some_other_header.h
#ifndef SOME_OTHER_HEADER_H
#define SOME_OTHER_HEADER_H
#include "some_header.h" // this header uses some_header.h
struct bar {
struct foo x;
};
#endif
And a program can now include both header files without getting an error like redefinition of 'foo'
.
File: main.cpp
#include "some_header.h"
#include "some_other_header.h"
int main() {}
A non-standard but quite popular alternative to the classic header guards shown above is #pragma once
which does the same thing (if your preprocessor supports it):
File: some_header.h
#pragma once
// no need for a named macro or #endif
struct foo { ... };
Upvotes: 0
Reputation: 72
There is no such thing as translating foo.h
as FOO_H
, nor such thing as "defining that a .h has already been included". Using preprocessor variables is just the standard way C developers ensure that .h are not included twice.
In C preprocessor, you can use things such as #if
, #else
and #endif
in order to make logic. You can also #define
variables, to store information. You can also use the function defined(...)
to check if a C-preprocessor variable is already defined. The #ifdef MY_VARIABLE
directive is just a shorthand for #if defined(MY_VARIABLE)
, and #ifndef
is just the opposite of that.
On the other hand, you don't want a .h to be included twice, there are several ways to do this, but the standard way is:
/* Check if my variable has already been declared */
#ifndef MY_aWeSoMe_VARIBLE
/* If we are in here, it mean that it is not */
/* So let's declare it */
#define MY_aWeSoMe_VARIBLE
/* You can write some more code here, like your .h stuff */
/* And of course, it's time to close the if */
#endif /* This closes the MY_aWeSoMe_VARIABLE ifndef */
The 1st time your complier will include the .h
, MY_aWeSoMe_VARIABLE
won't be defined yet, so preprocessor will get inside the if
, define the variable, include all the .h
's code. If your compiler comes to include the .h
a 2nd or more time, the variable will already be defined, so the preprocessor won't get inside the if
. Since all the .h
's content is inside the if
, it won't do anything.
Since naming a variable MY_aWeSoMe_VARIABLE
is pretty stupid, people tend to name it like MY_FILE_NAME
, or MY_FILE_NAME_H
, but this is not mandatory, practices actually vary from one dev to another.
Upvotes: 1