luserXtrog said:
Ok, thanks.
I know that disagreeing with someone like Rob Pike leads to a greater
than usual risk of being wrong, but I'm going to take the risk.
I disagree with this rule, quite strongly.
Here's what he wrote:
Simple rule: include files should never include include files.
If instead they state (in comments or implicitly) what files
they need to have included first, the problem of deciding
which files to include is pushed to the user (programmer)
but in a way that's easy to handle and that, by construction,
avoids multiple inclusions. Multiple inclusions are a bane
of systems programming. It's not rare to have files included
five or more times to compile a single C source file. The Unix
/usr/include/sys stuff is terrible this way.
There's a little dance involving #ifdef's that can prevent a file
being read twice, but it's usually done wrong in practice - the
#ifdef's are in the file itself, not the file that includes it.
The result is often thousands of needless lines of code passing
through the lexical analyzer, which is (in good compilers)
the most expensive phase.
Just follow the simple rule.
Note that the web page is dated February 21, 1989 (it's safe to assume
it wasn't originally a web page). Two decades later, compiler speed
is less of an issue. If making the compiler's preprocessor go through
a few thousand lines of code means I can write my code in a more
maintainable manner, it's well worth it.
As for putting the #ifdefs in the including file rather than in the
included file, I disagree with that as well. The #ifdef trick
requires inventing a unique macro name for each include file. Using a
consistent convention is impractical when include files come from
multiple sources. If I need a #include "foo.h", don't make me
remember remember whether I have to write #ifdef FOO_H or #ifdef H_FOO
(or #ifdef __FOO, and remind myself to complain to the author about
using a reserved identifier).
Now if rearranging the way headers are included could reduce the
time it takes to compile a large project from, say, 2 hours to 1
hour, it would be worth looking into -- but only if I can be sure it
won't hurt maintainability and cost me far more time and frustration
than it saves me. An hour spent waiting for a long compilation
to finish (letting me do other construct work in the meantime) is
much better than an hour or more spent modifying every file that
depends on foo.h because one if its internal dependencies changed,
and another hour or two pulling out my hair because I made a subtle
error on one of the changes.
It should be possible for a preprocessor to recognize the #ifdef
trick, remember that it's already seen a header, and take a shortcut
that avoids re-scanning the entire file (*if* that's going to save
enough time to be worthwhile).
It's the compiler's job to make my job easier, not vice versa.
I wonder if Rob Pike still holds the same opinion.