Search code examples
cclangincludeheader-files

Include needed headers in both .c and the corresponding .h or only in the .h?


Assume I have a module filter.c/filter.h.
That module exposes a function in the header:
uint32_t filterStuff(uint32_t input);

This means I need to include stdint.h, and I need it in both the filter.c AND the filter.h
In the past I simply included stdint.h in filter.h. Since filter.h is also included inside filter.c the code has the int32 typedef available as well and everything works.

But when I check that code with clang-tidy I get a

no header providing "uint32_t" is directly included

warning from misc-include-cleaner.

Does this suggest I should include stdint.h in both filter.c AND filter.h separately? Is that considered good style?

NOTE: I'm asking only about the case where something is included in the header directly belonging to some c-file: foo.c and foo.h. I'm not asking about trusting correct indirect includes from headers NOT directly belonging to said module.


Solution

  • The header filter.h should include <stdint.h> since one of the functions it declares needs one of the types from <stdint.h>, and a header should be self-contained, minimal and idempotent. (For more discussion, see Should I use #include in headers? and other questions.)

    The code in filter.c necessarily uses filter.h, so it does not really need to include <stdint.h> directly. However, other source files might use filter.h for some parts of the code but also use types from <stdint.h> separately from the use mandated by filter.h. It becomes contentious whether those other files should include <stdint.h> directly. The argument in favour of doing so is that if the code ceases to need filter.h, then the <stdint.h> header will need to be added to the source to provide the now-missing declarations. The argument against that is "the code will have to be changed when it stops using filter.h, and adding the <stdint.h> header would simply be one of the other necessary changes".

    I tend towards the "against" view — I would not include <stdint.h>. But I'm not 100% consistent about it (is anyone 100% consistent?). If the policy is to use tools that complain if you don't include the file directly, then follow the rules imposed by that policy and the tools you use.

    I still regard self-containment as important. If I include a header x.h, I should not need to include other headers y.h and z.h (that I may not even be fully cognizant of) in order to use the facilities of x.h.