Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What things should absolutely never be included in a header file?

If for example I'm working with a documented industry standard format that has a lot of constants, is it a good practice to define them in a header file (if I'm writing a parser for that format)?

What functions should go into the header file?
What functions shouldn't?

share|improve this question

closed as too broad by gnat, MichaelT, Robert Harvey, amon, Michael Kohne Mar 3 '14 at 14:28

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

Short and painless: definitions and declartions that are needed in more than one module. – ott-- Oct 6 '12 at 20:51
up vote 24 down vote accepted

What to put in headers:

  • The minimal set of #include statements that are needed to make the header compilable when the header is included in some source file.
  • Preprocessor symbol definitions of things that need to be shared and that can only accomplished via the preprocessor. Even in C, preprocessor symbols are best kept to a minimum.
  • Forward declarations of structures that are needed to make the structure definitions, function prototypes, and global variable declarations in the body of the header compilable.
  • Definitions of data structures and enumerations that are shared amongst multiple source files.
  • Declarations for functions and variables whose definitions will be visible to the linker.
  • Inline function definitions, but take care here.

What doesn't belong in a header:

  • Gratuitous #include statements. Those gratuitous includes cause recompilation of things that don't need to be recompiled, and can at times make it so a system can't compile. Don't #include a file in a header if the header itself doesn't need that other header file.
  • Preprocessor symbols whose intent could be accomplished by some mechanism, any mechanism, other than the preprocessor.
  • Lots and lots of structure definitions. Split those up into separate headers.
  • Inline definitions of functions that require an additional #include, that are subject to change, or that are too big. Those inline functions should have little if any fan out, and if they do have fan out, it should be localized to stuff defined in the header.
share|improve this answer

In addition to what has already been said.

H files should always contain:

  • Source code documentation!!! At a minimum, what is the purpose of the various parameters and return values of the functions.
  • Header guards, #ifndef MYHEADER_H #define MYHEADER_H ... #endif

H files should never contain:

  • Any form of data allocation.
  • Function definitions. Inline functions may be a rare exception in some cases.
  • Anything labelled static.
  • Typedefs, #defines or constants that have no relevance to the rest of the application.

(I would also say that there is never any reason to use non-constant global/extern variables, anywhere, but that's a discussion for another post.)

share|improve this answer
I agree with everything, except what you have highlighted. If you are making a library, yes, you should document or the users of your library. For an in-house project you shouldn't need to clutter your headers with documentation, if you use good, self explanatory variable and function names. – martiert Oct 8 '12 at 14:02
@martiert I'm also of the "let the code speak for itself" school. Yet you should at the very least always document your functions, even if nobody but yourself will use them. Things of particular interest are: in case the function has error handling, what error codes does it return and under which conditions does it fail? What happens to parameters (buffers, pointers etc) if the function fails? Another thing that is very relevant is: are the pointer parameters returning something to the caller, ie do they expect allocated memory? -> – user29079 Oct 8 '12 at 14:09
It should be obvious to the caller what error handling is done inside the function and what is not done. If the function expects an allocated buffer, it will most likely leave the out-of-bounds checks to the caller as well. If the function relies on another function to be executed, this must be documented (ie run link_list_init() before link_list_add()). And finally, if the function has a "side-effect" such as creating files, threads, timers or whatever, it should be stated in the documentation. -> – user29079 Oct 8 '12 at 14:12
Maybe "source code documentation" is too broad here, this really belongs to the source code. "Usage documentation" with input and output, pre- and postconditions and side-effects should definitely go there, not in epic but in a brief form. – Secure Oct 8 '12 at 14:19
A bit belated, but +1 for documentation. Why does this class exist? The code does not speak for itself. What does this function do? RTFC (read the fine .cpp file) is an obscene four letter acronym. One should never have to RTFC for understanding. The prototype in the header should summarize, in some extractable comment (e.g., doxygen), what the arguments are and what the function does. Why does this data member exist, what does it contain, and is the value in meters, feet, or furlongs? That too is another subject for (extractable) comments exist. – David Hammen Oct 14 '13 at 12:55

I would probably never say never, but statements that generate data and code as they are parsed should not be in a .h file.

Macros, inline functions and templates may look like data or code, but they do not generate code as they are parsed, but instead when they are used. These items often need to be used in more than one .c or .cpp, so they belong in the .h.

In my view, a header file should have the minimum practical interface to a corresponding .c or .cpp. The interface can include #defines, class, typedef, struct definitions, function prototypes, and less preferred, extern definitions for global variables. However, if a declaration is used in only one source file, it probably should be excluded from the .h and be contained in the source file instead.

Some may disagree, but my personal criteria for .h files is that they #include all other .h files that they need to be able to compile. In some cases, this can be a lot of files, so we have some effective methods to reduce external dependencies like forward declarations to classes that let us use pointers to objects of a class without including what could be a big tree of include files.

share|improve this answer

Header file should have the following organization:

  • type and constant definitions
  • external object declarations
  • external function declarations

Header files should never contain object definitions, only type definitions and object declarations.

share|improve this answer
What about inline function definitions? – Kos Oct 6 '12 at 10:00
If the inline function is a “helper” function that’s only used inside one C module, then put it in that .c file only. If, the inline function must be visible to two or more modules, the put it inside the header file. – theD Oct 6 '12 at 10:16
Also, if the function has to be visible across a library boundary, don't make it inline as that forces everyone who uses the library to recompile every time you modify things. – Donal Fellows Oct 6 '12 at 12:11
@DonalFellows: That's a backhanded solution. A better rule: Don't put stuff in headers that is subject to frequent modification. There's nothing wrong with inlining a short little function in a header if the function has no fanout and has a clear definition that will only change if the underlying data structure changes. If the function definition changes because the underlying structure definition changed, yeah, you have to recompile everything, but your going to have to do that anyway because the structure definition changed. – David Hammen Oct 6 '12 at 14:11

Statements that generate data and code as they are parsed, should not be in a .h file. As far as my point of view is concerned, a header file should only have the minimum practical interface to a corresponding .c or .cpp.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.