Why include guards?
up vote
14
down vote
favorite
Include guards, as defined here, are used to prevent loading the same code twice at compilation.
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
c++ c gcc compiler-construction preprocessor
add a comment |
up vote
14
down vote
favorite
Include guards, as defined here, are used to prevent loading the same code twice at compilation.
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
c++ c gcc compiler-construction preprocessor
5
Some people do intentionally include the same file twice (where the second inclusion has a real effect). This works, this is valid, so changing this would break existing code.
– user743382
Jan 13 '14 at 11:25
add a comment |
up vote
14
down vote
favorite
up vote
14
down vote
favorite
Include guards, as defined here, are used to prevent loading the same code twice at compilation.
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
c++ c gcc compiler-construction preprocessor
Include guards, as defined here, are used to prevent loading the same code twice at compilation.
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
c++ c gcc compiler-construction preprocessor
c++ c gcc compiler-construction preprocessor
edited yesterday
mrflash818
6361018
6361018
asked Jan 13 '14 at 11:22
ximus
10219
10219
5
Some people do intentionally include the same file twice (where the second inclusion has a real effect). This works, this is valid, so changing this would break existing code.
– user743382
Jan 13 '14 at 11:25
add a comment |
5
Some people do intentionally include the same file twice (where the second inclusion has a real effect). This works, this is valid, so changing this would break existing code.
– user743382
Jan 13 '14 at 11:25
5
5
Some people do intentionally include the same file twice (where the second inclusion has a real effect). This works, this is valid, so changing this would break existing code.
– user743382
Jan 13 '14 at 11:25
Some people do intentionally include the same file twice (where the second inclusion has a real effect). This works, this is valid, so changing this would break existing code.
– user743382
Jan 13 '14 at 11:25
add a comment |
7 Answers
7
active
oldest
votes
up vote
17
down vote
accepted
Simply because you might have wanted the compiler to load that file twice.
Remember, that #include
simply loads a file and puts its contents in the place of the directive. This file might be a header file, but may be useful and frequently used piece of source code as well.
Most modern compilers react to #pragma once
doing exactly what you want them to. Remember though, that this is a compiler extension not included in the language specification and it is generally a good idea to stick to include guards - you'll be certain, that it works on every compiler and in any circumstances.
1
Re#pragma once
: it's not 100% reliable, so you still need include guards.
– James Kanze
Jan 13 '14 at 11:31
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
2
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making#pragma once
standard, and rejected it because it wasn't (reliably) implementable.
– James Kanze
Jan 13 '14 at 11:39
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
2
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
|
show 1 more comment
up vote
11
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice
It can (or, pedantically, the preprocessor that deals with header inclusion can). Instead of using include guards, you could use a non-standard but widely supported extension
#pragma once
to indicate that this header should only be included once.
and have a sensible default behaviour?
The language doesn't specify this behaviour by default, largely because the language dates back to times when tracking included headers could be prohibitively expensive, and partly because sometimes you do want to include a header more than once. For example, the standard <assert.h>
header can be reincluded with or without NDEBUG
defined to change the behaviour of the assert
macro.
#pragma once
is a preprocessor feature though, not a compiler feature.
– datenwolf
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
1
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
1
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
1
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
|
show 3 more comments
up vote
9
down vote
Because there are bizarre edge cases where re-including a file is useful.
Contrived ugly example: Suppose you had an #include
file mymin.h
like this:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
You could then do something like this:
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
Now, you have two overloads of min
for different types, and a good candidate for http://thedailywtf.com/. Who needs templates? ;-)
Note that lots of modern preprocessors support #pragma once
, which is a much nicer way of achieving the same effect as include guards. However, it's unfortunately non-standard.
in this case why don't#define
both A and B before including the header?
– phuclv
Jan 13 '14 at 12:53
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-include
ing a file could have a different effect each time.
– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
add a comment |
up vote
4
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because it's not the compiler doing the include processing. It's done by the preprocessor which is essentially a text transformation engine. And for text transformation engine it can make perfect sense if the same include appears multiple times when processing a piece of text.
Let sink this in for a moment: The compiler does not process #include
s. This is what makes it impossible to make sensible decisions on symbol redefinitions by the compiler.
Other languages implement modules as a part of the language, and in those languages things are not processed as a text substitution and the compiler actually has knowledge about the import semantics.
add a comment |
up vote
0
down vote
Include guards protect against symbol redefinition and including the same files multiple times.
The compiler needs this mechanism because for obvious reasons, it does not include a mechanism to analyze and decide which code version to consider. Think of what would happen if the same function signature in two different header files only the return type is different.
Assuming the content is exactly the same only it's included from multiple headers, The compiler would require extra computing power and memory to keep track of the code it already included.
So it would be error prone and inneficient
add a comment |
up vote
0
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because then it wouldn't be a C compiler. The language is specified such that #include
creates a textual transclusion, and doing something different to the specification would break valid code.
The obvious follow-up question, "could we change the C Standard?" still has to find some way to avoid the same breakage of existing valid code.
One thing a compiler could legitimately do is to emit a warning when a non-empty (after processing #ifdef
and the like) file is multiply included without some indicator that it's intentional. If you're sufficiently motivated, perhaps you could prepare a suitable patch for your favourite compiler(s)?
BTW, you'll find that the problem gets very hard as soon as you have to come up with a good robust definition of "same code".
add a comment |
up vote
-1
down vote
Even if compiler decides to do that, it needs to keep track of huge number of files, and many times (as commented by itwasntpete), compiler has no way to distinguish between actual code and header file.
4
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
add a comment |
7 Answers
7
active
oldest
votes
7 Answers
7
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
17
down vote
accepted
Simply because you might have wanted the compiler to load that file twice.
Remember, that #include
simply loads a file and puts its contents in the place of the directive. This file might be a header file, but may be useful and frequently used piece of source code as well.
Most modern compilers react to #pragma once
doing exactly what you want them to. Remember though, that this is a compiler extension not included in the language specification and it is generally a good idea to stick to include guards - you'll be certain, that it works on every compiler and in any circumstances.
1
Re#pragma once
: it's not 100% reliable, so you still need include guards.
– James Kanze
Jan 13 '14 at 11:31
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
2
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making#pragma once
standard, and rejected it because it wasn't (reliably) implementable.
– James Kanze
Jan 13 '14 at 11:39
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
2
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
|
show 1 more comment
up vote
17
down vote
accepted
Simply because you might have wanted the compiler to load that file twice.
Remember, that #include
simply loads a file and puts its contents in the place of the directive. This file might be a header file, but may be useful and frequently used piece of source code as well.
Most modern compilers react to #pragma once
doing exactly what you want them to. Remember though, that this is a compiler extension not included in the language specification and it is generally a good idea to stick to include guards - you'll be certain, that it works on every compiler and in any circumstances.
1
Re#pragma once
: it's not 100% reliable, so you still need include guards.
– James Kanze
Jan 13 '14 at 11:31
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
2
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making#pragma once
standard, and rejected it because it wasn't (reliably) implementable.
– James Kanze
Jan 13 '14 at 11:39
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
2
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
|
show 1 more comment
up vote
17
down vote
accepted
up vote
17
down vote
accepted
Simply because you might have wanted the compiler to load that file twice.
Remember, that #include
simply loads a file and puts its contents in the place of the directive. This file might be a header file, but may be useful and frequently used piece of source code as well.
Most modern compilers react to #pragma once
doing exactly what you want them to. Remember though, that this is a compiler extension not included in the language specification and it is generally a good idea to stick to include guards - you'll be certain, that it works on every compiler and in any circumstances.
Simply because you might have wanted the compiler to load that file twice.
Remember, that #include
simply loads a file and puts its contents in the place of the directive. This file might be a header file, but may be useful and frequently used piece of source code as well.
Most modern compilers react to #pragma once
doing exactly what you want them to. Remember though, that this is a compiler extension not included in the language specification and it is generally a good idea to stick to include guards - you'll be certain, that it works on every compiler and in any circumstances.
edited Jan 13 '14 at 11:47
answered Jan 13 '14 at 11:27
Spook
16k1063111
16k1063111
1
Re#pragma once
: it's not 100% reliable, so you still need include guards.
– James Kanze
Jan 13 '14 at 11:31
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
2
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making#pragma once
standard, and rejected it because it wasn't (reliably) implementable.
– James Kanze
Jan 13 '14 at 11:39
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
2
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
|
show 1 more comment
1
Re#pragma once
: it's not 100% reliable, so you still need include guards.
– James Kanze
Jan 13 '14 at 11:31
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
2
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making#pragma once
standard, and rejected it because it wasn't (reliably) implementable.
– James Kanze
Jan 13 '14 at 11:39
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
2
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
1
1
Re
#pragma once
: it's not 100% reliable, so you still need include guards.– James Kanze
Jan 13 '14 at 11:31
Re
#pragma once
: it's not 100% reliable, so you still need include guards.– James Kanze
Jan 13 '14 at 11:31
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
@JamesKanze - What do you want to say by "not 100% reliable"?
– Spook
Jan 13 '14 at 11:36
2
2
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making
#pragma once
standard, and rejected it because it wasn't (reliably) implementable.– James Kanze
Jan 13 '14 at 11:39
That there are cases when it is impossible to detect whether two includes refer to the same file or not. They don't occur in simple, stand alone systems (at least not that I know of), but can (and in practice do, albeit rarely) occur once you start networking. The committee actually discussed making
#pragma once
standard, and rejected it because it wasn't (reliably) implementable.– James Kanze
Jan 13 '14 at 11:39
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
@JamesKanze Ok, may be worth noticing.
– Spook
Jan 13 '14 at 11:45
2
2
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
@Roddy Not just from symbolic links---at least under Unix, there are ways of working around this. But when an imported file system is mounted at two different places. (Strangely enough, this happens more often than one might expect.)
– James Kanze
Jan 13 '14 at 13:03
|
show 1 more comment
up vote
11
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice
It can (or, pedantically, the preprocessor that deals with header inclusion can). Instead of using include guards, you could use a non-standard but widely supported extension
#pragma once
to indicate that this header should only be included once.
and have a sensible default behaviour?
The language doesn't specify this behaviour by default, largely because the language dates back to times when tracking included headers could be prohibitively expensive, and partly because sometimes you do want to include a header more than once. For example, the standard <assert.h>
header can be reincluded with or without NDEBUG
defined to change the behaviour of the assert
macro.
#pragma once
is a preprocessor feature though, not a compiler feature.
– datenwolf
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
1
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
1
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
1
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
|
show 3 more comments
up vote
11
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice
It can (or, pedantically, the preprocessor that deals with header inclusion can). Instead of using include guards, you could use a non-standard but widely supported extension
#pragma once
to indicate that this header should only be included once.
and have a sensible default behaviour?
The language doesn't specify this behaviour by default, largely because the language dates back to times when tracking included headers could be prohibitively expensive, and partly because sometimes you do want to include a header more than once. For example, the standard <assert.h>
header can be reincluded with or without NDEBUG
defined to change the behaviour of the assert
macro.
#pragma once
is a preprocessor feature though, not a compiler feature.
– datenwolf
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
1
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
1
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
1
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
|
show 3 more comments
up vote
11
down vote
up vote
11
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice
It can (or, pedantically, the preprocessor that deals with header inclusion can). Instead of using include guards, you could use a non-standard but widely supported extension
#pragma once
to indicate that this header should only be included once.
and have a sensible default behaviour?
The language doesn't specify this behaviour by default, largely because the language dates back to times when tracking included headers could be prohibitively expensive, and partly because sometimes you do want to include a header more than once. For example, the standard <assert.h>
header can be reincluded with or without NDEBUG
defined to change the behaviour of the assert
macro.
Why can't my compiler (GCC) detect that it is loading the same code twice
It can (or, pedantically, the preprocessor that deals with header inclusion can). Instead of using include guards, you could use a non-standard but widely supported extension
#pragma once
to indicate that this header should only be included once.
and have a sensible default behaviour?
The language doesn't specify this behaviour by default, largely because the language dates back to times when tracking included headers could be prohibitively expensive, and partly because sometimes you do want to include a header more than once. For example, the standard <assert.h>
header can be reincluded with or without NDEBUG
defined to change the behaviour of the assert
macro.
edited Jul 29 '14 at 8:05
answered Jan 13 '14 at 11:28
Mike Seymour
213k19332551
213k19332551
#pragma once
is a preprocessor feature though, not a compiler feature.
– datenwolf
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
1
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
1
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
1
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
|
show 3 more comments
#pragma once
is a preprocessor feature though, not a compiler feature.
– datenwolf
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
1
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
1
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
1
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
#pragma once
is a preprocessor feature though, not a compiler feature.– datenwolf
Jan 13 '14 at 11:29
#pragma once
is a preprocessor feature though, not a compiler feature.– datenwolf
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
@datenwolf: Indeed, if you want to regard the first few translation stages as "preprocessing".
– Mike Seymour
Jan 13 '14 at 11:29
1
1
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
@datenwolf: That's irrelevant to this question about basic compilation, where all that matters is that it's part of the translation process, which we might as well loosely call "compilation", but I've added a note that might keep some pedants happy.
– Mike Seymour
Jan 13 '14 at 11:32
1
1
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
@datenwolf By whom? The standard specifies a total of 9 steps in program translation. The term "preprocessor" is a colloquial expression (not exact) for the first 6.
– James Kanze
Jan 13 '14 at 11:34
1
1
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
@datenwolf What compiler runs the preprocessor as a separate process? (Not that it matters, of course. g++, and probably a lot of other compilers, run the front-end, the optimizer and the back-end as separate processes.)
– James Kanze
Jan 13 '14 at 11:35
|
show 3 more comments
up vote
9
down vote
Because there are bizarre edge cases where re-including a file is useful.
Contrived ugly example: Suppose you had an #include
file mymin.h
like this:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
You could then do something like this:
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
Now, you have two overloads of min
for different types, and a good candidate for http://thedailywtf.com/. Who needs templates? ;-)
Note that lots of modern preprocessors support #pragma once
, which is a much nicer way of achieving the same effect as include guards. However, it's unfortunately non-standard.
in this case why don't#define
both A and B before including the header?
– phuclv
Jan 13 '14 at 12:53
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-include
ing a file could have a different effect each time.
– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
add a comment |
up vote
9
down vote
Because there are bizarre edge cases where re-including a file is useful.
Contrived ugly example: Suppose you had an #include
file mymin.h
like this:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
You could then do something like this:
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
Now, you have two overloads of min
for different types, and a good candidate for http://thedailywtf.com/. Who needs templates? ;-)
Note that lots of modern preprocessors support #pragma once
, which is a much nicer way of achieving the same effect as include guards. However, it's unfortunately non-standard.
in this case why don't#define
both A and B before including the header?
– phuclv
Jan 13 '14 at 12:53
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-include
ing a file could have a different effect each time.
– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
add a comment |
up vote
9
down vote
up vote
9
down vote
Because there are bizarre edge cases where re-including a file is useful.
Contrived ugly example: Suppose you had an #include
file mymin.h
like this:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
You could then do something like this:
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
Now, you have two overloads of min
for different types, and a good candidate for http://thedailywtf.com/. Who needs templates? ;-)
Note that lots of modern preprocessors support #pragma once
, which is a much nicer way of achieving the same effect as include guards. However, it's unfortunately non-standard.
Because there are bizarre edge cases where re-including a file is useful.
Contrived ugly example: Suppose you had an #include
file mymin.h
like this:
// mymin.h : ugly "pseudo-template" hack
MINTYPE min(MINTYPE a, MINTYPE b)
{
return (a < b) ? a : b;
}
You could then do something like this:
#define MINTYPE int
#include "mymin.h"
#define MINTYPE double
#include "mymin.h"
Now, you have two overloads of min
for different types, and a good candidate for http://thedailywtf.com/. Who needs templates? ;-)
Note that lots of modern preprocessors support #pragma once
, which is a much nicer way of achieving the same effect as include guards. However, it's unfortunately non-standard.
edited Jan 13 '14 at 13:21
answered Jan 13 '14 at 11:31
Roddy
45.3k35145239
45.3k35145239
in this case why don't#define
both A and B before including the header?
– phuclv
Jan 13 '14 at 12:53
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-include
ing a file could have a different effect each time.
– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
add a comment |
in this case why don't#define
both A and B before including the header?
– phuclv
Jan 13 '14 at 12:53
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-include
ing a file could have a different effect each time.
– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
in this case why don't
#define
both A and B before including the header?– phuclv
Jan 13 '14 at 12:53
in this case why don't
#define
both A and B before including the header?– phuclv
Jan 13 '14 at 12:53
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-
include
ing a file could have a different effect each time.– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc _ I did warn it was contrived... It's just to illustrate that re-
include
ing a file could have a different effect each time.– Roddy
Jan 13 '14 at 12:59
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
@LưuVĩnhPhúc - I've changed the "example". but this is still a case of "don't try this at home".
– Roddy
Jan 13 '14 at 13:22
add a comment |
up vote
4
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because it's not the compiler doing the include processing. It's done by the preprocessor which is essentially a text transformation engine. And for text transformation engine it can make perfect sense if the same include appears multiple times when processing a piece of text.
Let sink this in for a moment: The compiler does not process #include
s. This is what makes it impossible to make sensible decisions on symbol redefinitions by the compiler.
Other languages implement modules as a part of the language, and in those languages things are not processed as a text substitution and the compiler actually has knowledge about the import semantics.
add a comment |
up vote
4
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because it's not the compiler doing the include processing. It's done by the preprocessor which is essentially a text transformation engine. And for text transformation engine it can make perfect sense if the same include appears multiple times when processing a piece of text.
Let sink this in for a moment: The compiler does not process #include
s. This is what makes it impossible to make sensible decisions on symbol redefinitions by the compiler.
Other languages implement modules as a part of the language, and in those languages things are not processed as a text substitution and the compiler actually has knowledge about the import semantics.
add a comment |
up vote
4
down vote
up vote
4
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because it's not the compiler doing the include processing. It's done by the preprocessor which is essentially a text transformation engine. And for text transformation engine it can make perfect sense if the same include appears multiple times when processing a piece of text.
Let sink this in for a moment: The compiler does not process #include
s. This is what makes it impossible to make sensible decisions on symbol redefinitions by the compiler.
Other languages implement modules as a part of the language, and in those languages things are not processed as a text substitution and the compiler actually has knowledge about the import semantics.
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because it's not the compiler doing the include processing. It's done by the preprocessor which is essentially a text transformation engine. And for text transformation engine it can make perfect sense if the same include appears multiple times when processing a piece of text.
Let sink this in for a moment: The compiler does not process #include
s. This is what makes it impossible to make sensible decisions on symbol redefinitions by the compiler.
Other languages implement modules as a part of the language, and in those languages things are not processed as a text substitution and the compiler actually has knowledge about the import semantics.
answered Jan 13 '14 at 11:28
datenwolf
131k9128231
131k9128231
add a comment |
add a comment |
up vote
0
down vote
Include guards protect against symbol redefinition and including the same files multiple times.
The compiler needs this mechanism because for obvious reasons, it does not include a mechanism to analyze and decide which code version to consider. Think of what would happen if the same function signature in two different header files only the return type is different.
Assuming the content is exactly the same only it's included from multiple headers, The compiler would require extra computing power and memory to keep track of the code it already included.
So it would be error prone and inneficient
add a comment |
up vote
0
down vote
Include guards protect against symbol redefinition and including the same files multiple times.
The compiler needs this mechanism because for obvious reasons, it does not include a mechanism to analyze and decide which code version to consider. Think of what would happen if the same function signature in two different header files only the return type is different.
Assuming the content is exactly the same only it's included from multiple headers, The compiler would require extra computing power and memory to keep track of the code it already included.
So it would be error prone and inneficient
add a comment |
up vote
0
down vote
up vote
0
down vote
Include guards protect against symbol redefinition and including the same files multiple times.
The compiler needs this mechanism because for obvious reasons, it does not include a mechanism to analyze and decide which code version to consider. Think of what would happen if the same function signature in two different header files only the return type is different.
Assuming the content is exactly the same only it's included from multiple headers, The compiler would require extra computing power and memory to keep track of the code it already included.
So it would be error prone and inneficient
Include guards protect against symbol redefinition and including the same files multiple times.
The compiler needs this mechanism because for obvious reasons, it does not include a mechanism to analyze and decide which code version to consider. Think of what would happen if the same function signature in two different header files only the return type is different.
Assuming the content is exactly the same only it's included from multiple headers, The compiler would require extra computing power and memory to keep track of the code it already included.
So it would be error prone and inneficient
edited Jan 13 '14 at 12:12
answered Jan 13 '14 at 11:57
Pandrei
3,90731938
3,90731938
add a comment |
add a comment |
up vote
0
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because then it wouldn't be a C compiler. The language is specified such that #include
creates a textual transclusion, and doing something different to the specification would break valid code.
The obvious follow-up question, "could we change the C Standard?" still has to find some way to avoid the same breakage of existing valid code.
One thing a compiler could legitimately do is to emit a warning when a non-empty (after processing #ifdef
and the like) file is multiply included without some indicator that it's intentional. If you're sufficiently motivated, perhaps you could prepare a suitable patch for your favourite compiler(s)?
BTW, you'll find that the problem gets very hard as soon as you have to come up with a good robust definition of "same code".
add a comment |
up vote
0
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because then it wouldn't be a C compiler. The language is specified such that #include
creates a textual transclusion, and doing something different to the specification would break valid code.
The obvious follow-up question, "could we change the C Standard?" still has to find some way to avoid the same breakage of existing valid code.
One thing a compiler could legitimately do is to emit a warning when a non-empty (after processing #ifdef
and the like) file is multiply included without some indicator that it's intentional. If you're sufficiently motivated, perhaps you could prepare a suitable patch for your favourite compiler(s)?
BTW, you'll find that the problem gets very hard as soon as you have to come up with a good robust definition of "same code".
add a comment |
up vote
0
down vote
up vote
0
down vote
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because then it wouldn't be a C compiler. The language is specified such that #include
creates a textual transclusion, and doing something different to the specification would break valid code.
The obvious follow-up question, "could we change the C Standard?" still has to find some way to avoid the same breakage of existing valid code.
One thing a compiler could legitimately do is to emit a warning when a non-empty (after processing #ifdef
and the like) file is multiply included without some indicator that it's intentional. If you're sufficiently motivated, perhaps you could prepare a suitable patch for your favourite compiler(s)?
BTW, you'll find that the problem gets very hard as soon as you have to come up with a good robust definition of "same code".
Why can't my compiler (GCC) detect that it is loading the same code twice and have a sensible default behaviour?
Because then it wouldn't be a C compiler. The language is specified such that #include
creates a textual transclusion, and doing something different to the specification would break valid code.
The obvious follow-up question, "could we change the C Standard?" still has to find some way to avoid the same breakage of existing valid code.
One thing a compiler could legitimately do is to emit a warning when a non-empty (after processing #ifdef
and the like) file is multiply included without some indicator that it's intentional. If you're sufficiently motivated, perhaps you could prepare a suitable patch for your favourite compiler(s)?
BTW, you'll find that the problem gets very hard as soon as you have to come up with a good robust definition of "same code".
edited yesterday
answered yesterday
Toby Speight
16k133965
16k133965
add a comment |
add a comment |
up vote
-1
down vote
Even if compiler decides to do that, it needs to keep track of huge number of files, and many times (as commented by itwasntpete), compiler has no way to distinguish between actual code and header file.
4
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
add a comment |
up vote
-1
down vote
Even if compiler decides to do that, it needs to keep track of huge number of files, and many times (as commented by itwasntpete), compiler has no way to distinguish between actual code and header file.
4
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
add a comment |
up vote
-1
down vote
up vote
-1
down vote
Even if compiler decides to do that, it needs to keep track of huge number of files, and many times (as commented by itwasntpete), compiler has no way to distinguish between actual code and header file.
Even if compiler decides to do that, it needs to keep track of huge number of files, and many times (as commented by itwasntpete), compiler has no way to distinguish between actual code and header file.
answered Jan 13 '14 at 11:26
Pranit Kothari
5,562846109
5,562846109
4
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
add a comment |
4
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
4
4
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
Makes no sense. It's got to keep track of the same number of #defines for the header guards...
– Roddy
Jan 13 '14 at 11:27
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f21090041%2fwhy-include-guards%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
Some people do intentionally include the same file twice (where the second inclusion has a real effect). This works, this is valid, so changing this would break existing code.
– user743382
Jan 13 '14 at 11:25