2

Is there any reason not to write one header file that #includes all other header files and just #include that one header in each c file?

Each header file is setup #ifndef ... #define ... #endif

To clarify the duplicates; I was asking about user written code not system headers and the other possible duplicate didn't have answers that specified why it wasn't a good idea.

Thanks for the answers, I hadn't thought through some of them. I will look a taking the hybrid approach of some smaller headers for modules that fit together. This is for a codebase that I have taken over, it's very much a web I'm slowly trying to untangle.

LogicTom
  • 93
  • 1
  • 9
  • possible duplicate of [Is it right to simply include all header files?](http://stackoverflow.com/questions/8101576/is-it-right-to-simply-include-all-header-files) – Jongware May 24 '15 at 21:33
  • I do not think it's a duplicate @Jongware, they do not ask the same thing! – gsamaras May 24 '15 at 21:36
  • [This](http://stackoverflow.com/questions/5138259/is-it-a-good-idea-to-put-all-of-your-includes-in-one-header-file?rq=1) might be a better candidate for duplicate. –  May 24 '15 at 21:39

4 Answers4

3

The reason we split up header files and implementation files into separate files in the first place (aside from code readability) is to enable incremental building by the compiler. That is, if we make a change in HeadearA.h that only ImplA.c and ImplB.c need, there is no need to recompile ImplC.c through ImplZ.c. If you do it your way, however, there is no way for the compiler to know that, and you will wind up recompiling all of the .c files for every rebuild, regardless of necessity. For small projects with small build times, this is okay. For larger projects that have build times nearing 30 minutes, this becomes prohibitive.

  • 2
    30 minutes of build time... sounds like a c++ project. – chqrlie May 24 '15 at 21:29
  • It is; and to be fair, the longest time I've seen for a C project is around ~5 minutes, but the principle is the same, I feel. –  May 24 '15 at 21:30
  • Such large C projects are fairly rare. I can think of glibc, gcc, X-Windows, the Linux Kernel... most C projects rebuild from scratch in seconds on modern machines with enough RAM. – chqrlie May 24 '15 at 21:33
  • @chqrlie: Hm... somehow, most of the (C) projects I work on usually build in about ~2-3 minutes as I typically work on larger projects (which is still annoying to wait). I guess for most projects it shouldn't matter as much. –  May 24 '15 at 21:35
  • @chqrlie: depends. My current project includes quite some autogenerated code. But - acknowledged, it still compiler in under one minute on my old core 2 duo notebook from hdd. Hmm.. now I'm curious how long it takes on my desktop. – too honest for this site May 24 '15 at 21:45
2

What you suggest is possible: many projects use this convention.

Some advantages:

  • Simplicity of file heading
  • Simpler dependencies in Makefile, no need for complex autogenerated dependency lists
  • Early detection of name clashes.
  • No recursive include conundrums
  • No subtle bugs due to different include orders
  • Faster compilation if you use precompiled headers.

Some drawbacks:

  • Any modification in a header file will cause all source files in the project to be recompiled.
  • Encourages lack of proper encapsulation
  • Slower compile time for individual files (fix this with precompiled headers if it becomes a performance issue)
chqrlie
  • 131,814
  • 10
  • 121
  • 189
2

For a non-trivial project, a combination of both policies is often used: One header which includes commonly used system headers like stdbool.h, stdint.h, stdatomic.h, etc. As these never change, they are note relevant for rebuild.

You also might include some project-settings which are required by most/all modules, so you don't have to care about them when writing a new module (or change every module when refactoring them).

And then you have specific headers which represent your module-dependency tree. These are included as required. This not only speeds up building (not compiling) the project, but also can be used by doc-tools like doxygen to automatically create the dependency tree for the documentation, so you don't have to track every change manually. A similar approach may be used by an IDE for quick access to dependant headers/modules.

One disadvantage which expecially appies to C is called namespace pollution. As C does not allow for custom namespaces, every included header will have its symbols added to the namespace of the current compilation unit. For Macros, this might be even worse, as they are plain text-replacements with very limited knowledge of the context (for this, also check inline vs. function-macro).

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • The 'name space' pollution and the extended build times are the two main reasons to NOT group all the headers into a single header file. The whole idea behind makefiles, etc is to reduce the build time. I'm from back in the days when a build could take hours and hours and hours. In those days (when programs were much much smaller) we would do all we could to minimize the amount of file compiles. Now, programs are much much larger and compiling a file typically happens almost instantly, but when there are hundreds/thousands of files, we still need to do what we can to minimize – user3629249 May 24 '15 at 22:57
  • @user3629249: Did you actually read my answer? I just detailed than. You do certainly not think the system headers will change that often, don't you? For some projects the build time is mostly irrelevant on decent host hardware, so it would also be no issue to combine some only occassionally changing headers; expecially if these are anyway included in most modules. Then it actually make no difference. I think I stated clear when and when not to use which approach. I'm in that business long enough to know how it was back then, too. And I certainly do nor argue _for_ bundling _all_ headers. – too honest for this site May 25 '15 at 01:11
  • What answer? I just read the whole thing again and all I see from you is two comments, no answer. – user3629249 May 26 '15 at 20:24
  • @user3629249: Then I cannot help you - sorry. Apparently others think different. – too honest for this site May 26 '15 at 22:04
2

The main problem is that you end up with a big bowl of spaghetti code and everything knows about everything ..eventually .anything you change has repercussions, and you end up having to refactor to re-modularize... You don't have the tiny little reminder of actually including some header to make the decision of x should know about y.

But there isn't anything intrinsically wrong with it aside from the normal issues of symbol visibility and macro expansion, which should be edge cases..

Grady Player
  • 14,399
  • 2
  • 48
  • 76