-1

[edit] It seems some people are commenting and voting without reading my post. Please read it before commenting. For instance: if you think I am against including files more than once, then you are missing the point of my post.

I would like to trap sloppy programming by outputting an error when some include files are included twice.

I use #pragma once for include files that intend to include within other include files. That works great.

I know I can do a variation of "guard macros" to accomplish this. But is there a better way? Another #pragma or a gcc compile option?

This is a sample of a guard macro:

#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN

the entire file

#endif /* !FILE_FOO_SEEN */

This would work for me:

#ifdef FILE_FOO_SEEN

#error "FILE_FOO inappropriately included twice.

#endif /* FILE_FOO_SEEN */

#define FILE_FOO_SEEN
/* Active Code */

[edit] Note: I am not asking for why it is necessary to support including header files multiple times. That is a common case and supported with the a gcc pragma. I am asking for the case when I have specific include files that I do not want included more than once. If someone were to include them more than once, then it would be one of two actions: 1) Change the trap to a #pragma once, or 2) change the code to eliminate the dependency.

Because there is a special pragma to support multiple include, I thought someone might have good techniques to avoid this as well.

[edit] Add some of the rules we follow related to our use of header files:

  1. Each .c file has a companion .h file with the function prototypes. You can think of this .h file as the interface to the .c file. This .h file may also contain structure definitions and enums that are consumed or returned by the functions. This .h file does not need to be included in any other .h file because other .h files do not use functions.

  2. We do not create a companion .h file for .c files that contain main().

  3. Sometimes structures and enums are used independently of the functions that return or consume them. For these cases the enums and structures are moved to an independent .h file. This .h file will contain a #pragma once because it could be included multiple times.

  4. Opaque structures are preferred.

  5. Doxygen documentation that documents the interface is contained in the .h files. This works well because the .h file contains the complete interface to the .c file.

  6. We make exceptions to these rules as needed, but for the most part we adhere to these rules.

  7. Following these rules makes writing unit tests easier as the complete interface is easy to identify and understand.

Be Kind To New Users
  • 9,672
  • 13
  • 78
  • 125
  • 6
    There will definitely be cases (and it's probably the common case) where a header gets included more than once (via multiple include paths) and shouldn't be considered an error. – Oliver Charlesworth Jul 01 '15 at 23:11
  • 2
    I second Oliver's comment and I would not classify having an include file added more than once sloppy. In fact I would classify relying on one include file to include something that another file needs as sloppy. – missimer Jul 02 '15 at 00:14
  • @OliverCharlesworth yeah, that is why I was careful to put in my description "some include files". It is obviously a common case to include more than once (so obvious that I did not point it out in my question) because gcc has a special pragma for it. I am asking about the case where I want to ensure that it is not included twice. – Be Kind To New Users Jul 02 '15 at 06:13
  • How about adhering to Header guards? – WedaPashi Jul 02 '15 at 06:25
  • @WedaPashi Header Guards are for the common case of wanting to allow a header file to be included more than once. I am asking about the case when I want to have an error when they are included more than once. – Be Kind To New Users Jul 02 '15 at 06:31
  • Michael, why do you think it matters that some headers should not be included more than once? What concern do you have that isn't cured by doing what everyone else does — using some form of header guard (`#ifndef` or `#pragma`)? What is the benefit you perceive from not having a specific header included twice? – Jonathan Leffler Jul 02 '15 at 06:51
  • @JonathanLeffler I am doing what everyone else does: I use #pragma once or code guards on include files that are included more than once. I do this quite often. Because of our coding standard, many of our include files do not have any reason to be included twice. I keep a tidy code repository and I don't want extra includes. I would add the trap to those files. An example of a include file that has no reason to be included more than once is one that only contains function prototypes. – Be Kind To New Users Jul 02 '15 at 07:04
  • I'm not wholly on-board with your assertion that a header that only declares function prototypes need only be included once. Actually, it is headers that define enumerations or structure types that can only be included once; headers that just define function prototypes can be included as often as you like without incurring any damage except (perhaps) to compile time. And the header guards avoid even that overhead. Can you quote your coding standard that prevents you simply protecting headers with header guards. Is there a rationale behind it? – Jonathan Leffler Jul 02 '15 at 07:10

2 Answers2

2

I don't think you should do it (remind me not to use your headers, please, if you decide to go ahead with this scheme).

However, if you start with the well-known mechanism for preventing damage when a header is included twice:

#ifndef FILE_FOO_SEEN
#define FILE_FOO_SEEN

…the entire file…

#endif /* !FILE_FOO_SEEN */

then you can easily adapt it to generate an error when the file is included twice (as you recognize in the question):

#if defined(FILE_FOO_SEEN)
#error File foo.h already included
#else
#define FILE_FOO_SEEN

…the entire file…

#endif /* FILE_FOO_SEEN */

Since #error is part of Standard C, it should work — at least to get a diagnostic message into the output from the compilation. It should, but might not (Solaris of yesteryear — I'm looking at you!), prevent a successful compilation.

Depending on your compilers, you may be able to fine-tune the error handling strategy, though frankly, it is best (by far) to simply allow the header to be included multiple times.

Headers should be self-contained and idempotent.

  • Self-contained means that you should not be required to include anything else explicitly in order to be able to use the header (you simply write #include "header.h" and it works).
  • Idempotent means that if you include the file twice, by any mechanism, it works safely.

The C Standard requires this for the standard headers. Strictly, <assert.h> isn't strictly idempotent, but the others are all idempotent. They're all self-contained, though <inttypes.h> is allowed to include <stdint.h>.

You should follow the lead of the standard — it provides good techniques to use.


Related questions

I make no claim that this is either a complete list or an unbiassed list of links.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

tl;dr you may not be able to avoid multiple includes


Some more explanation why...

It's totally normal that different parts of a program include the same header. The goal an #include wants to achieve is that needed structures and functions are known before they get used. Since multiple includes of the same file slowdown the compilation and circular includes may result in infinite loops the #pragma once and #ifndef - #define - #endif construct got invented. You may read that #pragma once is deprecated and obsolete but it gets used anyway and anywhere...

Similar there is/was an #import instead of #include that only includes the file once but that's a rarity AFAIK, at least in C/C++ code.

Now let's say we produce clean code without double includes and slap each developer with warnings who may do it. The problem you get now is: what if multiple classes in different files need the same data structure? Since you stick to single includes only, you would need to know the sequence in which the files get included.

Example

Class A needs something from class B but both need Header X with a struct. You would include B before class A and within the file of class A you include header X. If you now change the dependencies of the classes you may need to move the header X include to another class on top of the chain.

Now imagine this for a big project with many files and even more people who work on them independently. It gets pretty obvious that nobody wants to disentangle the dependencies if its possible at all. So you just use #pragma once and everybody is happy and that's basically the whole story about it.

Possible ways to print errors

#warning not entirely platform-independent.

#error stops the compilation/preprocessing.

This third way should be supported by GCC as well as MSVC:

#pragma message("double include")
#pragma message "double include"
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Eve Keksdose
  • 56
  • 1
  • 4
  • Note that `#error` is part of Standard C. Neither `#warning` nor `#pragma message` is part of Standard C. How much that matters depends on how much portability matters to you. – Jonathan Leffler Jul 02 '15 at 06:36
  • @Eve Thank you for #pragma message(). For our include files that have structures we use #pragma once. I am thinking about include files that are not subject to being included more than once such as include files that only include function prototypes. Because of our coding standards, that is a common case for us. I want to avoid a tangled mess of include files and trap that condition. – Be Kind To New Users Jul 02 '15 at 06:36
  • @Eve Do you have a reference for which compilers have deprecated pregma once? I found some references in 2003, but then I found that it was undeprecated. I use it even tho it is not standard because it is widely supported and less subject to typos. If sometime it is removed, then it would be trivial to replace with code guards. – Be Kind To New Users Jul 02 '15 at 06:55
  • @MichaelPotter: The basic idea is that the `#ifndef` / `#define` header guard is covered by the language standard, while `#pragma once` is not. – DevSolar Jul 02 '15 at 15:49