Header include order

D

Derrick Coetzee

It seems like, in every C source file I've ever seen, there has been a
very definite include order, as follows:

- include system headers
- include application headers
- include the header associated with this source file

For example, in a file hello.c:

#include <stdio.h>
#include "utils.h"
#include "hello.h"

(Incidentally I think that a source file which doesn't include the header
file which exports its symbols is _very_ bad, as this is a good way to
check for inconsistencies for free.)

I would argue that the standard order of header including is wrong,
and that the correct order is the reverse. Consider this scenario:

hello.c:
#include <stdlib.h>
#include "hello.h"

hello.h:
struct blah {
size_t size;
};

hello2.c
#include "hello.h"

Inexplicably (from the perspective of the person doing the including)
the file hello.h will cause compiler errors in hello2.c but not in hello.c.
If hello.c were written first, and then the include file used elsewhere,
the error would appear to be "new", and not be caught by those who wrote
hello.c, implementing the functionality exported by hello.h.

If this include order is used, this problem is averted:

- include the header associated with this source file
- include application headers
- include system headers

This is good for two reasons:
1. All headers must now include any system headers they need, and will
fail immediately if they don't.
2. Every header will be included in at least ONE source file before
anything else (the source file associated with that header), allowing
any intra-application dependencies to be caught.

Does anyone have a reasonable justification for the standard include
order that I haven't thought of? Thanks.
 
M

Morris Dovey

Derrick said:
It seems like, in every C source file I've ever seen, there has been a
very definite include order, as follows:

- include system headers
- include application headers
- include the header associated with this source file

You have a good eye.
For example, in a file hello.c:

#include <stdio.h>
#include "utils.h"
#include "hello.h"

(Incidentally I think that a source file which doesn't include the header
file which exports its symbols is _very_ bad, as this is a good way to
check for inconsistencies for free.)

Hmm. Ok. I think that it depends on the situation; but if you
don't do what you think is bad, you probably won't be wrong.
I would argue that the standard order of header including is wrong,
and that the correct order is the reverse. Consider this scenario:

Let me break in here to suggest that it isn't unusual for my
headers to need definitions provided by the system headers...
hello.c:
#include <stdlib.h>
#include "hello.h"

hello.h:
struct blah {
size_t size;
};

/This/ is bad practice. Structures, unions, arrays, and variables
should only be declared - not defined - in header files. Placing
definitions in header files, while not strictly illegal, is
asking for trouble.
hello2.c
#include "hello.h"

Inexplicably (from the perspective of the person doing the including)
the file hello.h will cause compiler errors in hello2.c but not in hello.c.
If hello.c were written first, and then the include file used elsewhere,
the error would appear to be "new", and not be caught by those who wrote
hello.c, implementing the functionality exported by hello.h.

Does anyone have a reasonable justification for the standard include
order that I haven't thought of?

Already answered.

HTH
 
R

Rouben Rostamian

It seems like, in every C source file I've ever seen, there has been a
very definite include order, as follows:

- include system headers
- include application headers
- include the header associated with this source file

[description of pitfalls snipped]
If this include order is used, this problem is averted:

- include the header associated with this source file
- include application headers
- include system headers

I completely agree with your reasons for suggesting this.
They make good sense and enforce good code design.

But old habits die hard. I just can't bring myself to
reverse the order of header, despite reason and logic.

Old dog, new tricks...
 
M

Morris Dovey

Morris said:
/This/ is bad practice. Structures, unions, arrays, and variables should
only be declared - not defined - in header files. Placing definitions in
header files, while not strictly illegal, is asking for trouble.

Please ignore the comment about bad practice. Due to faulty
wiring I read that as a definition, which it obviously isn't.

If you ignore that, then the remainder is valid ( but not much
called-for )-:
 
R

Richard Heathfield

[This is a rather interesting idea, which probably won't get the attention
it deserves because it proposes a change to the way code is laid out, and
many clc-ers don't seem to like such changes.]

Derrick said:
If this include order is used, this [idempotency failure] problem is averted:

- include the header associated with this source file
- include application headers
- include system headers

This is good for two reasons:
1. All headers must now include any system headers they need, and will
fail immediately if they don't.

Not quite true. All headers must either include any system headers they
need, or follow another such header in the batting order. You have reduced
the scale of the problem (and I think that's a good thing in itself), but
not eliminated it.
2. Every header will be included in at least ONE source file before
anything else (the source file associated with that header), allowing
any intra-application dependencies to be caught.

Interesting point.
Does anyone have a reasonable justification for the standard include
order that I haven't thought of? Thanks.

Only a philosophical one, which hadn't really occurred to me until you
raised the subject. I think the existing order is as it is because it gives
a constant narrowing of focus. "Right, let's have some big old headers, our
good friends stdio, stdlib, string... Okay, now let's pull in some local
stuff that we used on XFoo... xfoo.h, xbar.h... now, for /this/ program
we'll need ybaz.h, which we'll write in a minute... okay, let's write
ybaz".

In other words, I think it's pure habit.
 
M

Moosebumps

If this include order is used, this problem is averted:
- include the header associated with this source file
- include application headers
- include system headers

It's a coding standard at my company (not widely followed) to do this.
Always #include Foo.h as the first line of Foo.c. That way you're assured
that whenever you #include Foo.h from any other file, it will compile.
There is no messing with the orders of headers to fix compile errors, and
conversely organizing headers for aesthetics will not cause any compile
errors.
 
J

Jarno A Wuolijoki

I would argue that the standard order of header including is wrong,
and that the correct order is the reverse.
If this include order is used, this problem is averted:

- include the header associated with this source file
- include application headers
- include system headers

Does anyone have a reasonable justification for the standard include
order that I haven't thought of? Thanks.

You may forget to include stdlib in hello.c and
then when you change hello.h to use stddef instead
it breaks?
 
D

Dan Pop

In said:
You have a good eye.

Hmm. Ok. I think that it depends on the situation; but if you
don't do what you think is bad, you probably won't be wrong.


Let me break in here to suggest that it isn't unusual for my
headers to need definitions provided by the system headers...

Then, your headers should include the system headers they need.
I couldn't agree more with the OP on this point.
/This/ is bad practice. Structures, unions, arrays, and variables
should only be declared - not defined - in header files. Placing
definitions in header files, while not strictly illegal, is
asking for trouble.

Sheer nonsense, as far as structure and union definitions are concerned.
When I need a struct tm, I use the definition provided by <time.h> and
that never caused my any trouble. Using my own definition, OTOH, would
be a sure recipe for headaches.

Dan
 
D

Dan Pop

In said:
It seems like, in every C source file I've ever seen, there has been a
very definite include order, as follows:

- include system headers
- include application headers
- include the header associated with this source file

For example, in a file hello.c:

#include <stdio.h>
#include "utils.h"
#include "hello.h"

(Incidentally I think that a source file which doesn't include the header
file which exports its symbols is _very_ bad, as this is a good way to
check for inconsistencies for free.)
Obviously.

I would argue that the standard order of header including is wrong,
and that the correct order is the reverse. Consider this scenario:

hello.c:
#include <stdlib.h>
#include "hello.h"

hello.h:
struct blah {
size_t size;
};

hello2.c
#include "hello.h"

Inexplicably (from the perspective of the person doing the including)
the file hello.h will cause compiler errors in hello2.c but not in hello.c.

It's not inexplicable. If hello.h is written this way, then including
If this include order is used, this problem is averted:

- include the header associated with this source file
- include application headers
- include system headers

This is good for two reasons:
1. All headers must now include any system headers they need, and will
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fail immediately if they don't.

This is a general rule, *these days*. The system headers are not included
first so that other headers no longer have to include them.
2. Every header will be included in at least ONE source file before
anything else (the source file associated with that header), allowing
any intra-application dependencies to be caught.

This is a valid point.
Does anyone have a reasonable justification for the standard include
order that I haven't thought of? Thanks.

Yes, from a historical perspective. Back when disks were much slower
than they are today (especially on micros and low end minis, whose
fastest mass storage devices were floppy disks), you didn't want to
have to open and read any more header files than strictly necessary.
Therefore, headers didn't include other headers, they merely documented
their dependencies. Using the traditional include order, each header file
had to be opened and read exactly once, speeding up the compilation
process, at the expense of some extra care on the programmer's side.

But there is another reason, that still applies. It is very easy to
inadvertently declare an identifier already declared in a system header.
Especially if your implementation provides many C99 functions as
extensions, along with its own specific extensions. If you include
the application headers first, the compiler will report the problem
as being generated by a system header. I've seen more than one
programmer completely baffled when that happened and suspecting his
implementation to be broken, because including a system header must,
"by definition", cause no problems. Imagine the following scenario:
one of your headers, say "appmath.h", declares:

long round(double);

and everything works fine, until someone else tries to compile your
program on a platform declaring

double round(double);

as a C99 extension in <math.h> (or even having C99 conforming libraries).
Since <math.h> was included after the application header, the error
will be reported in <math.h>, resulting in a maximum of confusion
(especially if the compiler was not kind enough to indicate the
actual location of the other declaration). Now, if that happened in
"appmath.h", nobody would expect the system headers to be broken, because
the problem is correctly reported as belonging to "appmath.h".

So, going from more general to more specific still has its merits...

Dan
 
M

Morris Dovey

Dan said:
Then, your headers should include the system headers they need.
I couldn't agree more with the OP on this point.

Me too. It /does/ look as if I'd have done better to turn off the
computer and get some sleep. Apologies to Derrick.
Sheer nonsense, as far as structure and union definitions are concerned.
When I need a struct tm, I use the definition provided by <time.h> and
that never caused my any trouble. Using my own definition, OTOH, would
be a sure recipe for headaches.

More of the same. This bit of stupidity I /did/ catch last night.
Now I find myself wondering what I could have been thinking. I
swear I was only drinking coffee...
 
A

Alan Balmer

Then, your headers should include the system headers they need.
I couldn't agree more with the OP on this point.
Me, too :) The standard headers, particularly, are guaranteed to work
in any order and even if included more than once.
Sheer nonsense, as far as structure and union definitions are concerned.
When I need a struct tm, I use the definition provided by <time.h> and
that never caused my any trouble. Using my own definition, OTOH, would
be a sure recipe for headaches.
Definition vs. declaration?

I prefer that nothing in a header file reserve storage.

The above is OK, but a header file containing

struct blah {
size_t size;
} xyz;

is bad practice, imo.
 
D

Dan Pop

In said:
Me, too :) The standard headers, particularly, are guaranteed to work
in any order and even if included more than once.

Definition vs. declaration?

When it comes to structures and unions (as types, not as objects), I
consider:

struct foo;

to be a declaration and:

struct foo { int bar, baz; };

to be a definition.
I prefer that nothing in a header file reserve storage.

It's more than a simple preference in my case :)

Dan
 
A

Alan Balmer

When it comes to structures and unions (as types, not as objects), I
consider:

struct foo;

to be a declaration and:

struct foo { int bar, baz; };

to be a definition.
What do you call

struct foo foo_thing;

?

Of course, my speculation as to what Morris really meant is outdated,
since it appears he really meant to get some sleep.
It's more than a simple preference in my case :)

Dan

When writing code, it's an absolute. When maintaining legacy code,
I've sometimes ignored it if the fix would take too long.

I'm making progress, though - in the last couple of years at this
location, the product builds have declined from about 360,000 warnings
to under 70,000 ;-)

Still have a bunch of modules that haven't been made compliant enough
to turn on the ANSI compiler switch.
 
E

E. Robert Tisdale

Derrick said:
It seems like, in every C source file I've ever seen,
there has been a very definite include order, as follows:

- include system headers
- include application headers
- include the header associated with this source file

For example, in a file hello.c:

#include <stdio.h>
#include "utils.h"
#include "hello.h"

(Incidentally I think that a source file which doesn't include
the header file which exports its symbols is _very_ bad,
as this is a good way to check for inconsistencies for free.)

I would argue that the standard order of header including is wrong,
and that the correct order is the reverse. Consider this scenario:

hello.c:
#include <stdlib.h>
#include "hello.h"

hello.h:
struct blah {
size_t size;

Where is the definition for size_t?
};

hello2.c
#include "hello.h"

Inexplicably (from the perspective of the person doing the including)
the file hello.h will cause compiler errors in hello2.c but not in hello.c.
If hello.c were written first, and then the include file used elsewhere,
the error would appear to be "new", and not be caught by those who wrote
hello.c, implementing the functionality exported by hello.h.

If this include order is used, this problem is averted:

- include the header associated with this source file
- include application headers
- include system headers

This is good for two reasons:
1. All headers must now include any system headers they need, and will
fail immediately if they don't.
2. Every header will be included in at least ONE source file before
anything else (the source file associated with that header), allowing
any intra-application dependencies to be caught.

Does anyone have a reasonable justification
for the standard include order that I haven't thought of?

A header file is a file that you #include
near the top of a translation unit (or another header file).
You can #include files at any point in a translation unit
(or header file) but you probably shouldn't call them header files.

According to Sun Microsystems,

http://docs.sun.com/db/doc/805-4955/6j4mg806h?a=view

header files should be both idempotent and self-contained
so that it doesn't matter which order you include them
which reduces your observation to a "coding style" issue.

I would write

> cat hello.h
#ifndef guard_hello_h
#define guard_hello_h 1
#include<stdlib.h>
typedef struct blah {
size_t size;
} blah;
#endif//guard_hello_h

> cat hello.c
#include"hello.h"
// . . .

As a general rule of thumb, don't put anything in a header file
that would, by itself, cause the compiler to emit code.
 
A

Alex

E. Robert Tisdale said:
Derrick Coetzee wrote:

said:
I would argue that the standard order of header including is wrong,
Where is the definition for size_t?

said:
I would write
> cat hello.h
#ifndef guard_hello_h
#define guard_hello_h 1
#include<stdlib.h>
typedef struct blah {
size_t size;
} blah;
#endif//guard_hello_h
> cat hello.c
#include"hello.h"
// . . .

Where is the definition for size_t?

Alex
 
E

Eric Sosman

Alan said:
When writing code, it's an absolute. When maintaining legacy code,
I've sometimes ignored it if the fix would take too long.

I agree with Dan and Alan for the proverbial 99.44% of
all uses of header files, but there *are* cases where it
can be useful to put definitions in headers. A few I've
run across:

- When part of the code is generated by a "helper"
program, it's often convenient to have the helper
write a header. This is often seen in connection
with static initializations, where the main file
contains something like

static const struct thingummy big_table[] = {
#include "generated.h"
};

There's a quibble about whether the header in this
case "reserves storage" or not -- but at any rate,
it certainly doesn't contain declarations!

- Headers are a good place for widely-used `inline'
functions. Again, there's a quibble about whether
defining such a function "reserves storage," but
again it's clear that such a header contains more
than mere declarations.

- "Code generating" or "template" headers can be useful
in generating functions customized for particular
data types. For example, I've seen a customizable
sort generator that's used somewhat like

void sort_thing(struct thing *array, size_t count)
{
#define SORT_TYPE struct thing
#define SORT_COMPARE(x,y) ((x).key < (y).key)
#define SORT_ARRAYNAME array
#define SORT_COUNT count
#define SORT_ALGORITHM SORT_HEAPSORT
...
#include "sort_generator.h"
}

Note that it is quite often difficult or impossible
to re-package such a code generator as a macro, because
macros cannot themselves use preprocessor directives
and this can be limiting in such a situation. (For
example, consider how to handle the SORT_ALGORITHM
variation in a pure-macro setting.)

Still and all, these are exceptional cases and fairly far
from the norm. 99.44% of all headers, and perhaps more, should
do as Alan and Dan say.
 
E

E. Robert Tisdale

Eric said:
Alan said:
When writing code, it's an absolute. When maintaining legacy code,
I've sometimes ignored it if the fix would take too long.


I agree with Dan and Alan for the proverbial 99.44% of
all uses of header files, but there *are* cases where it
can be useful to put definitions in headers. A few I've
run across:

- When part of the code is generated by a "helper"
program, it's often convenient to have the helper
write a header. This is often seen in connection
with static initializations, where the main file
contains something like

static const struct thingummy big_table[] = {
#include "generated.h"
};

That's *not* a header file.
A header file is #included at the *head* of another file.
There's a quibble about whether the header in this
case "reserves storage" or not -- but at any rate,
it certainly doesn't contain declarations!

- Headers are a good place for widely-used `inline'
functions. Again, there's a quibble about whether
defining such a function "reserves storage," but
again it's clear that such a header contains more
than mere declarations.

- "Code generating" or "template" headers can be useful
in generating functions customized for particular
data types. For example, I've seen a customizable
sort generator that's used somewhat like

void sort_thing(struct thing *array, size_t count)
{
#define SORT_TYPE struct thing
#define SORT_COMPARE(x,y) ((x).key < (y).key)
#define SORT_ARRAYNAME array
#define SORT_COUNT count
#define SORT_ALGORITHM SORT_HEAPSORT
...
#include "sort_generator.h"
}

Again, this is *not* a header file.
Note that it is quite often difficult or impossible
to re-package such a code generator as a macro, because
macros cannot themselves use preprocessor directives
and this can be limiting in such a situation. (For
example, consider how to handle the SORT_ALGORITHM
variation in a pure-macro setting.)

Still and all, these are exceptional cases and fairly far
from the norm. 99.44% of all headers, and perhaps more, should
do as Alan and Dan say.

You are confused.
A file included by the C preprocessor directive
is *not* necessarily a header file.
A file with *.h extension is *not* necessarily a header file.
Neither the C preprocessor or the C programming language
specify file name extensions for header files.
 
D

Derrick Coetzee

According to Sun Microsystems,
http://docs.sun.com/db/doc/805-4955/6j4mg806h?a=view

header files should be both idempotent and self-contained
so that it doesn't matter which order you include them
which reduces your observation to a "coding style" issue.

I omitted the usual header guards for simplicitly. I fully support the
idea of each header including whatever other headers it depends
upon. In fact, the entire point of my post was that the include order
I advocate makes it easier to catch accidental omissions of other
headers that should be included from the header. Sorry if that
wasn't clear.
As a general rule of thumb, don't put anything in a header file
that would, by itself, cause the compiler to emit code.

True, but irrelevent.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top