views:

1222

answers:

6

Say I have a C program which is broken to a set of *.c and *.h files. If code from one file uses functions from another file, where should I include the header file? Inside the *.c file that used the function, or inside the header of that file?

E.g. file foo.c includes foo.h, which contains all declarations for foo.c; same for bar.c and bar.h. Function foo1() inside foo.c calls bar1(), which is declared in bar.h and defined in bar.c. Now the question is, should I include bar.h inside foo.h, or inside foo.c?

What would be a good set of rules-of-thumb for such issues?

+2  A: 

I include the most minimal set of headers possible in the .h file, and include the rest in the .c file. This has the benefit of sometimes reducing compilation times. Given your example, if foo.h doesn't really need bar.h but includes it anyway, and some other file includes foo.h, then that file will be recompiled if bar.h changes, even though it may not actually need or use bar.h.

mipadi
+3  A: 

I would only include header files in a *.h file that required for the header file itself. Header files that are needed for a source file, in my opinion, should be included in the source file so that the dependencies are obvious from the source. Header files should be be built to handle multiple inclusion so you could put it in both if required for clarity.

tvanfosson
+5  A: 

You should include foo.h inside foo.c. This way other c files that include foo.h won't carry bar.h unnecessarily. This is my advice for including header files:

  • Add include definitions in the c files - this way the file dependencies are more obvious when reading the code.
  • Split the foo.h in two separate files, say foo_int.h and foo.h. The first one carries the type and forward declarations needed only by foo.c. The foo.h includes the functions and types needed by external modules. This is something like the private and public section of foo.
  • Avoid cross references, i.e. foo references bar and bar references foo. This may cause linking problems and is also a sign of bad design
kgiannakakis
The only reason for creating a header is because more than one source file needs the information. The foo_int.h header should not be needed outside foo.h, so it should not be created or used - its contents can be placed directly in foo.c.
Jonathan Leffler
Continuing: you would use foo_int.h when you have more than one source file providing the functionality of 'foo.c' -- say foo1.c and foo2.c. Then the internal header makes sense. However, you should aim to keep things compact enough that the C file split is unnecessary.
Jonathan Leffler
I have found that splitting the files is a good technique, when you have long type, constant or MACRO definitions that are only needed for foo.c. It is better to have them in a header file than directly in source file. Adam Liss indicated a better solution, having everything in the same .h file
kgiannakakis
+2  A: 

The .h file should define the public interface (aka the api) to the functions in the .c file.

If the interface of file1 uses the interface of file2 then #include file2.h in file1.h

If the implementation in file1.c makes use of stuff in file2.c then file1.c should #include file2.h.

I must admit though that - because I always #include file1.h in file1.c - I normally wouldn't bother #including file2.h directly in file1.c if it was already #included in file1.h

If you ever find yourself in the situation where two .c files #include each others .h files then it is a sign that modularity has broken down and you ought to think about restructuring things a bit.

Dipstick
+2  A: 

Using the examples of foo.c and foo.h I've found these guidelines helpful:

  • Remember that the purpose of foo.h is to facilitate the use of foo.c, so keep it as simple, organized, and self-explanatory as possible. Be liberal with comments that explain how and when to use the features of foo.c -- and when not to use them.

  • foo.h declares the public features of foo.c: functions, macros, typedefs, and (shudder) global variables.

  • foo.c should #include "foo.h -- see discussion, and also Jonathan Leffler's comment below.

  • If foo.c requires additional headers for it to compile, include them in foo.c.

  • If external headers are required for foo.h to compile, include them in foo.h

  • Leverage the preprocessor to prevent foo.h from being included more than once. (See below.)

  • If for some reason an external header will be required in order for another .c file to use the features in foo.c, include the header in foo.h to save the next developer from unnecessary debugging. If you're averse to this, consider adding macro that will display instructions at compile-time if the required headers haven't been included.

  • Don't include a .c file within another .c file unless you have a very good reason and document it clearly.

As kgiannakakis noted, it's helpful to separate the public interface from the definitions and declarations needed only within foo.c itself. But rather than creating two files, it's sometimes better to let the preprocessor do this for you:

// foo.c
#define _foo_c_         // Tell foo.h it's being included from foo.c
#include "foo.h"
. . .

 

// foo.h
#if !defined(_foo_h_)   // Prevent multiple inclusion
#define _foo_h_

// This section is used only internally to foo.c
#ifdef _foo_c_
. . .
#endif

// Public interface continues to end of file.

#endif // _foo_h_       // Last-ish line in foo.h
Adam Liss
foo.c 'can' include foo.h -- nay, foo.c MUST include foo.h, and as the first header, which is an automatic check that foo.h is self-contained and hence usable by others.
Jonathan Leffler
Also, there is no point in the header including information that is only used internally in the implementation source file. The only information that goes in a header is public stuff that other files need.
Jonathan Leffler
Thanks ... answer updated to reference your comment.
Adam Liss
I'll sometimes #define macros differently, depending on whether foo.h is included directly by foo.c, to avoid duplicate prototypes/declarations, when the maintenance benefits grossly outweigh any resulting obfuscation.
Adam Liss
+2  A: 

As others have noted, a header foo.h should declare the information necessary to be able to use the facilities provided by a source file foo.c. This would include the types, enumerations and functions provided by foo.c. (You don't use global variables, do you? If you do, then those are declared in foo.h too.)

The header foo.h should be self-contained and idempotent. Self-contained means that any user can include foo.h and not need to worry about which other headers may be needed (because foo.h includes those headers). Idempotent means that if the header is included more than once, there is no damage done. That is achieved by the classic technique:

 #ifndef FOO_H_INCLUDED
 #define FOO_H_INCLUDED
 ...rest of the contents of foo.h...
 #endif /* FOO_H_INCLUDED */

The question asked:

File foo.c includes foo.h, which contains all declarations for foo.c; same for bar.c and bar.h. Function foo1() inside foo.c calls bar1(), which is declared in bar.h and defined in bar.c. Now the question is, should I include bar.h inside foo.h, or inside foo.c?

It will depend on whether the services provided by foo.h depend on bar.h or not. If other files using foo.h will need one of the types or enumerations defined by bar.h in order to use the functionality of foo.h, then foo.h should ensure that bar.h is included (by including it). However, if the services of bar.h are only used in foo.c and are not needed by those who use foo.h, then foo.h should not include bar.h

Jonathan Leffler