6

I'm building a main.c file to make use of functions out of a few different .h files. A few of those .h files (or rather, their .c source files) use the same includes (the standard but also some others like )

My question is: Is it okay if I just include those once for all header files in my main.c, or should I let every .h file include them individually and not include them in my main.c (considering I only use functions from those header files)?

Or should I do both?

How I do it now is:

dist.c:

#include "dist.h"
#include  <stdio.h>
#include  <unistd.h>
#include  "rpiGpio.h"
#include <pthread.h>
#include  <wiringPi.h>
#include  <softPwm.h>

Then for another:

cmps.c:

#include "cmps.h"
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include "rpiGpio.h"

Then in my main.c:

#include    <stdio.h>
#include    <stdlib.h>
#include    "dist.h"
#include    "cmps.h"

Thanks in advance!

Guinn
  • 1,355
  • 13
  • 29

2 Answers2

8

You should include standard headers above your own headers, and you should include all the dependencies for a file in that file. If you change the includes in one of your file, it shouldn't affect any other files. Each file should maintain its own list of header dependencies.

If, in your example, dist.h includes <stdio.h>, you should not rely on this outside dist.h. If you change dist.h so that it no longer depends on <stdio.h> and remove that #include, then your program breaks.

user229044
  • 232,980
  • 40
  • 330
  • 338
  • Sounds very logical the way you explain it, couldn't really make that up from the stuff I read about it. Thanks! – Guinn Jan 04 '15 at 18:49
2

I think the answer is "it depends". So long as you are consistent, I think it's OK. Some advantages and disadvantages of different approaches:

  1. Including a system header twice will not cause adverse effects (due to header guards); including your own headers twice should also not cause problems provided you use header guards too. However, arguably it may slow compilation.

  2. In some circumstances, particularly on older Unices, the order of inclusion of headers matters (sadly). Sometimes the order of #defines (e.g. #define _GNU_SOURCE) does matter with respect to #include. I've also had this happen with Linux include files for various internal bits of networking (I now forget what). For this reason, it's a good idea to always include your system includes (and the #defines they examine) in a consistent manner.

  3. One way to do that is to put all your system includes in a single include file of your own, and include them from each .c file; this produces much the same result as you would get with autoconf and its generated config.h. However, it may unnecessarily include files slowing compilation down.

  4. Some say put includes of system headers above your own includes. Whilst this is often seen as good practice, it doesn't work great if your own .h files reference types defined in system includes, e.g. stdint.h defines int32_t. If you include that in your .h file alone, you are back to a potential problem with include order and whether or not you've got your #define _GNU_SOURCE in the right place.

  5. Therefore my personal coding style is to have a config.h equivalent, which is included by all .h files and (for good measure) all .c files as the first include, which contains all the relevant system includes. It's not ideal for compile time, but that's what precompiled headers are for. I normally arrange system includes in alphabetical order, unless there is a reason not to.

  6. The alternative is to (carefully) do it by file, as @meagar suggests.

Community
  • 1
  • 1
abligh
  • 24,573
  • 4
  • 47
  • 84
  • I like the different approaches and the extend of your answer, though the part in @meagar 's answer that suggests that each file should be able to 'work' independent with its own list of header dependencies, and thus shouldn't malfunction if you change the includes in your main.c file, is the direct answer to my question! – Guinn Jan 04 '15 at 19:02
  • 1
    Including `"foo.h"` twice in some file like `"foo.c"` (and only once in other places) is a method to help test that `"foo.h"` is properly guarded. Do like the larger points-of-view. – chux - Reinstate Monica Jan 04 '15 at 19:04
  • 1
    1) Compilation is unlikely to suffer at all by including the same header file more than once. 2) If your compiler doesn't take include order into consideration, drop it immediately. It's broken. 3) Global headers are a bad habit shared by far too many people. 4) By not intermixing system and local header includes, you can avoid a lot of work with #defines. 5) Global header files... config.h are for things you can't reliably predict when writing the code; not for being lazy. – Clearer Mar 21 '15 at 03:25