Thread: Header file multiple inclusion question

  1. #1
    System.out.println("");
    Join Date
    Jan 2005
    Posts
    84

    Header file multiple inclusion question

    I understand about the whole

    Blah.h
    Code:
    ifndef BLAH_H
    #define BLAH_H
    
    
    /* code*/
    
    #endif
    Then when you want to include Blah. you do:

    Code:
    #include "Blah.h"
    So now you won't include the same file twice. But I was reading online and saw that it was better (faster compilation times) to do it this way. Something about the compiler lexical analyzer being the most expensive part of the compilation process (Sorry, I can't find the link anymore).

    Code:
    #ifndef BLAH_H
    #include "Blah.h"
    #endif
    Where you want the Blah.h file included. Have you guys heard of this? If so, is it worth it to go through a project that takes 3-5 minutes to compile to change all of them?

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I can't see how that could make much of a difference, but if you really feel like making a ton of changes, you could find out if it does actually make a difference. I think it's pretty bad programming practice to do it that way though.
    You might want to see if your compiler supports pre-compiled headers.

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    If so, is it worth it to go through a project that takes 3-5 minutes to compile to change all of them?
    Having to work with several projects of about 1000-2000 files in each... No... I prefer to have Header guards once in one place... there is enough headake to struggle with other issues
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Loctan View Post
    But I was reading online and saw that it was better (faster compilation times) to do it this way. Something about the compiler lexical analyzer being the most expensive part of the compilation process (Sorry, I can't find the link anymore).
    This sort of thing really depends on the implementation of the compiler (or, more accurately, the preprocessor).

    Some older preprocessors would parse an #include'd file completely, which essentially meant that the whole file had to be read in to detect include guards within that file, and that the file would be read multiple times if it was #include'd multiple times. Putting the include guard into the including file basically reduced the need to execute the #include directive. Some vendors claimed the issue was with the lexical analyser, which is true but misleading: the real issue was that those compilers implemented workarounds for some of the preprocessor inefficiencies in the subsequent lexical analysis phase.

    More modern preprocessors are a little smarter than those older preprocessors, and use techniques such as precompiled headers (which essentially means that the preprocessor does some smart caching, so it does not have to read files or expand macro definitions multiple times). With those preprocessors, there is nothing to gain by moving include guards out of the affected headers.

    Personally, I would not put include guards outside the affected headers. It is one more thing to be maintained, and the effort to do that exceeds the benefits when many source files include a particular header.

  5. #5
    System.out.println("");
    Join Date
    Jan 2005
    Posts
    84
    Thanks for the explanations guys. I have never had the opportunity to take a compiler course so I wasn't sure of all the details of this. Hopefully I can take one soon. For fun, if I get bored at work I will run some analysis with Eclipse 3.2 to compare both versions to see how long each takes. I already have some Java that should be able to replace it relatively easy (read: only take an hour to do instead of days by hand). I will be sure to post results when (if) I do it.

    Thanks again.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    precompiled headers (which essentially means that the preprocessor does some smart caching, so it does not have to read files or expand macro definitions multiple times).
    That's not doing the complexity of precompiled headers justice in the least.

    What some modern compilers do what really makes this technique unnecessary is this: they recognize the pattern. They know that if the first functional pp tokens in a file are "#ifndef" SYMBOL "#define" SYMBOL and the last token is "#endif", the file is under an include guard. The preprocessor will then put the name of the file into a list.
    On every #include, the preprocessor will first look up the file name in the list. If it finds it, it won't bother to even look at the file. "Been there, done that."

    Some compilers don't implement this trick, most notably Microsoft's. The MS compiler and compatibles have a different trick: just put
    #pragma once
    in the header file, and it will be put into a similar list.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CornedBee View Post
    That's not doing the complexity of precompiled headers justice in the least.
    I agree CornedBee. I gave one point from the complete story.
    Quote Originally Posted by CornedBee View Post
    What some modern compilers do what really makes this technique unnecessary is this: they recognize the pattern. They know that if the first functional pp tokens in a file are "#ifndef" SYMBOL "#define" SYMBOL and the last token is "#endif", the file is under an include guard. The preprocessor will then put the name of the file into a list.
    On every #include, the preprocessor will first look up the file name in the list. If it finds it, it won't bother to even look at the file. "Been there, done that."
    Which is what I vastly over-simplified with one word: "caching".

    It's actually the modern preprocessors that do what you describe, not the compiler proper, but yes. I'm saying this in the sense of the phases of compilation described in the standard (preprocessing [logically done by preprocessor] occurs before compilation [logically done by compiler]). The actual implementation with (some) modern compiler products is a bit different: some include the preprocessor and compiler in one executable and, although they do some things in different order, they give the same net effect. (We hope!)
    Quote Originally Posted by CornedBee View Post
    Some compilers don't implement this trick, most notably Microsoft's. The MS compiler and compatibles have a different trick: just put
    #pragma once
    in the header file, and it will be put into a similar list.
    I actually had mention of #pragma once in a draft of my previous post, but cut it out as an excess level of detail.

    The #pragma once was, originally, a workaround for preprocessors that don't do the tricks you described. The catch is, #pragma once is (or "was" in the first Microsoft compilers; I'm not sure offhand if that is still true) done in the compilation phase, and not in the preprocessor phase, affecting execution of lexical analysis done in the compilation phase. It is not a particularly efficient solution to the problem, hence the sort of comment quoted by Loctan.
    Last edited by grumpy; 05-03-2008 at 04:48 PM.

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    This technique was recommended, I believe, by Lakos in Large Scale C++ Software Design, and is called "redundant include file guards". The idea is that, even though the include file guard will protect against multiple inclusion. the redundancy will prevent header files from being opened, read, and closed unnecessarily.

  9. #9
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    It's too bad they didn't design compilers (and the standard) so that all headers were automatically only included once (unless you used some kind of #pragma many statement).

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Hm. That wouldn't be good for the code I wrote that had headers designed to be multiply included.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Dave_Sinkula View Post
    Hm. That wouldn't be good for the code I wrote that had headers designed to be multiply included.
    But how often is that the case?
    Almost every header file I've ever written had header guards.
    I'm not even sure what cases would require multiple inclusion of header files?

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I'm not even sure what cases would require multiple inclusion of header files?
    I cannot think of a good example either; it seems to me that in such cases a macro will suffice.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    I found the other way more confusing.
    http://cboard.cprogramming.com/showt...539#post186539
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Which is what I vastly over-simplified with one word: "caching".
    Well, no. The preprocessor doesn't cache anything, really. Rather, it remarks the fact that if it were to include the file again, it would have no effect, so it doesn't. But it doesn't actually store the information of the header for reuse. That's what precompiled headers do.

    It's actually the modern preprocessors that do what you describe, not the compiler proper,
    I was referring to the compiler whole.

    I'm not even sure what cases would require multiple inclusion of header files?
    Large tables, enums, etc. are sometimes fed from a header containing calls of an undefined macro. Define the macro the way you need it and include the file, then undefine the macro. Later, define it as something else and include the file again.
    The Mozilla source uses this, for example, for the CSS properties.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  15. #15
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Dave_Sinkula View Post
    I found the other way more confusing.
    http://cboard.cprogramming.com/showt...539#post186539
    So in the case where you'd actually want to include multiple times, they could have added a #pragma many statement (the opposite of #pragma once).
    That way in 99.999% of header files where you don't want it to be included more than once, you don't have to worry about adding include guards (which is a common noob mistake), and only in the rare cases when you do want it multiply included would you need to add an extra line of code.
    But we're stuck with the way it works now, so it doesn't make much difference what I think might have been a good feature...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. Defining multiple classes in the same header file
    By Stonehambey in forum C++ Programming
    Replies: 2
    Last Post: 08-14-2008, 10:36 AM
  3. Need help understanding Header Files
    By Kaidao in forum C++ Programming
    Replies: 11
    Last Post: 03-25-2008, 10:02 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM