Header File Included Only Once in Entire Program

How to include a file only once / Prevent Function Redefinitions in old C API from C++ Program

Abstract the C functionality behind a layer of indirection:

original structure (if I understand correctly this is what you have now):

file1.h -> #include included_c_api.h
file2.h -> #include included_c_api.h CAUSES errors.

new structure:

new_c_api.h -> wrapper over included_c_api.h functionality (w/ your own symbols)
new_c_api.c[pp] -> #include included_c_api.h
file1.h -> #include new_c_api.h
file2.h -> #include new_c_api.h

If the functionality exposed in included_c_api.h is very big, this solution could be impractical.

What exactly happens when a header file is included?

C and C++ are languages, which extensively uses feature called function forwarding. This means, that you can say, for instance:

void f(int i); /* note the semicolon */

This means: "I promise, that somewhere later in the source code someone will define, what the function f actually does". After such forward, you may use this function as it really existed and compiler will require someone to actually define this function later (if there is no definition, compilation will fail). This forward is called also a header, because it actually is a header of function definition:

void f(int i) /* Header */
/* Body */
{
/* ... */
}

Header file is a file, which contains mostly such forwards. You can use the header file to get access to functions defined somewhere else (for example in different compilation unit or external library) and then attach required object files or libraries to provide implementation of these header files. Apart from function forwards, in a header file you may also find structure definitions, constants or other items, which are required for proper use of defined functions.

How compiler matches your forward to actual implementation in .c file? Well simply - by the header. It attempts to find a function definition (implementation), which exactly matches the header you declared earlier.

What happens if you #include header file is that compiler (specifically, the preprocessor) copies the whole contents of header file into place, where you put your #include. That's all magic, nothing more happens.

During runtime, the header file does not matter at all, because your executable file consists only of executable code. Compiler either loads all functions available in the library (which is accessed by the header file) or (mostly probably, if optimization is turned on) chooses only these functions, which you actually used in your code.

The funny thing is, that compiler requires function definition (implementation) only if someone actually uses that function. Otherwise, the forward is ignored. Try:

void f(int i);

int main(int argc, char ** argv)
{
/* Do not use f here */

return 0;
}

Including header files in C/C++ more than once

Yes, it's useful when generating code with the preprocessor, or doing tricks like Boost.PP does.

For an example, see X Macros. The basic idea is that the file contains the body of the macro and you #define the arguments and then #include it. Here's a contrived example:

macro.xpp

std::cout << MESSAGE;
#undef MESSAGE

file.cpp:

int main() {
# define MESSAGE "hello world"
# include "macro.xpp"
}

This also allows you to use #if and friends on the arguments, something that normal macros can't do.

Programming with just header files?

Header files come with the concept of modularisation, i.e. of separating the source code of a large program into several independent parts, i.e. translation units. Thereby, implementation details are hidden to other translation units, and dependencies are dramatically reduced. But: if a translation unit A needs to call a function from another translation B, it needs to have the function prototype of the respective function, i.e. the function without the body - something like int functionFromB(int x); in order to tell the compiler how to call it. So translation unit A could simple write this prototype at the beginning; but usually functions from translation unit B (e.g. B.cpp) are exposed in a header file B.h, which comprises all the "public" functions of B in form of function prototypes. Same applies to type definitions and (global) variables. Then A simply can include B.h in order to have all the function prototypes et al. available without the necessity of knowing all the implementation details (like the function bodies).

So you can write a large program completely in .h-files; yet you have to tell the compiler to treat them as translation units (usually only .cpp-files are treated as such), and you still have to provide function prototypes et al...

With translation units, you have separate / independent modules. This is in contrast to a large monolithic block, which you get when you "paste" all the chunks of your program spread over different .h-files by #include-ing them "together". You can compile / test / distribute translation units separately, whereas a monolithic block cannot be compiled / tested / distributed partly.

When is it useful to include the same header multiple times in one file?

#include "file" means take the header file and put all of its content instead of the #include line.

We usually used headers for type definitions and for adding a forward declarations to a source files. defining same type twice in a file (a circular include will always cause it) gives compilation error, therefore we use #ifndef or #pragma once. (or both)

But we also can to put a repeating code and macros and include it several times, even in the same file. in such as case, we won't use #ifndef nor #pragma once. If you do so you must be extra careful, and do it only if you know what you are doing.

For example: If in some OS calling a specific system function (or even a c macro like: offsetof) cause a bunch of warnings, and it is bothering you, and you sure your code is good, but you don't want to disable all the warnings you've got on all the project or the file, you just want to disable it when you call the specific function.

//suppress the warnings: 
#if defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreorder"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wsequence-point"
#endif
#endif // __GNUC__

//here you call the function...
func(x,y,z);

//unsupress: bring back the warnings to normal state
#if defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif // __GNUC__

This will make your code to look very dirty, especially if you call the function several times.

One possible solution, (I'm not suggesting it is the best one...) is to make 2 headers, in one to suppress the warnings and in the other to cancel the suppression.

In that case your code may look like this:

#include "suppress.h"
func(x,y,z);
#include "unsuppress.h"

//.... more code come here
//now when call it again:
#include "suppress.h"
func(x,y,z);
#include "unsuppress.h"


Related Topics



Leave a reply



Submit