0

My project has several header files. Most of C source files include all of those, so nearly every source file contains the following lines:

#include "add.h"
#include "sub.h"
#include "mul.h"
#include "div.h"
#include "conv.h"
#include "comp.h"
// etc.

Should this be moved to some all.h or similar? Is there a better way to do this?

Danijel
  • 8,198
  • 18
  • 69
  • 133
  • 1
    How big is your project (thousands of source lines, or many millions of them)? How many contributors do you have (are you alone coding on your project, or do you have dozens of contributors)? – Basile Starynkevitch Feb 17 '17 at 08:25
  • 1
    What are you optimizing *for*? build times? line-count? ... or general developer convenience? – ideasman42 Feb 17 '17 at 08:29
  • 1
    There is also the third, somewhere-in-the-middle option, to have a `common.h` for stuff which is shared by pretty much all your translation units (headers like `stdint.h` come to my mind). – vgru Feb 17 '17 at 08:32

3 Answers3

3

There are pro and conses in both approaches (having one single all.h including all your headers, or not), so it is also a matter of opinion. And on a reasonably small project, having a single header file containing all your common declarations (and also definitions of static inline functions) is also possible.

See also this answer (which gives examples of both approaches).

A possible reason to have one single header (which includes other headers, even the system ones) is to enable pre-compilation of that header file. See this answer (and the links there).

A possible reason to favor several header files is readability and modularity. You might want to have one (rather small) header file per module and in every translation unit (practically every .c file) you would include only the minimal set of header files (in the good order).

Remember that C99 & C11 (and even C++14) do not have any notion of modules; in other words, modules in C are only a matter of conventions & habits. And conventions and habits are really important in C programs, so look at what other people are doing in existing free software projects (e.g. on github or sourceforge).

Notice that preprocessing is the first phase of most C compilers. Read documentation about your C preprocessor.

You practically would use a build automation system like GNU make. You may want to automatically generate dependencies (e.g. like here).

For a single-person project (of a few dozens of thousand source lines at most), I personally prefer to have a single header file, but that is a matter of opinion and taste (so a lot of people disagree). BTW, refactoring your project (to several header files) when it becomes large enough is quite easy to do (but harder to design); you'll just copy&paste some chunks of code in several new header files.

For a project involving several developers, you may want to favor the idea that most files (header or code) have one single developer responsible for them (with other developers making occasional changes to it).

Notice that header inclusion and preprocessing is a textual operation. You might in theory even avoid having header files and copy and paste the same declarations in your .c files but that is very bad practice so you should not do that (in hand-written code). However, some projects are generating C code (some sort of metaprogramming), and their C code generator (some script, or some tool like bison) could emit the same declarations in several files.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    Aren't headers file just linked during compilation and brought to memory whenever needed ? Doesn't that add an overhead when you put all headers in one header when you don't really use all functionality of some of the headers ? – Tony Tannous Feb 17 '17 at 08:26
  • 1
    Header files are not *linked*, they are *included* early during compilation, because the preprocessing is the first phase of most compilers. – Basile Starynkevitch Feb 17 '17 at 08:40
3

In each .c file it should be easy to know what includes it needs. By doing your way, you could lose track of what includes it needs, and another colleague will need to look for this file.

In another words, you shouldn't do that because you lose clarity in your code.

2501
  • 25,460
  • 4
  • 47
  • 87
alpereira7
  • 1,522
  • 3
  • 17
  • 30
3

There is also the third, somewhere-in-the-middle option, to have a minimum common.h for stuff which is shared by pretty much all your translation units (e.g. headers like stdint.h). Or perhaps you might decide to group add.h, sub.h and similar headers into a single ops.h header.

But having literally a single all.h header would make encapsulation/information hiding in C even harder than it is already. Does a math library in a spaceship microcontroller really need to know everything about life support systems?

Of course, C doesn't really have "first class encapsulation mechanisms", you can throw an extern function declaration pretty much everywhere, that's why it's rather important to stick to reasonable conventions and best practices.

vgru
  • 49,838
  • 16
  • 120
  • 201