Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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.

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 #includes. 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.

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

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".

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top