1 <!DOCTYPE HTML PUBLIC
"-//W3O//DTD W3 HTML 2.0//EN">
2 <!-- This collection of hypertext pages is Copyright 1995-7 by Steve Summit. -->
3 <!-- This material may be freely redistributed and used -->
4 <!-- but may not be republished or sold without permission. -->
7 <link rev=
"owner" href=
"mailto:scs@eskimo.com">
8 <link rev=
"made" href=
"mailto:scs@eskimo.com">
9 <title>20.2 Nested Header Files
</title>
10 <link href=
"sx6a.html" rev=precedes
>
11 <link href=
"sx7.html" rel=precedes
>
12 <link href=
"sx6.html" rev=subdocument
>
15 <H2>20.2 Nested Header Files
</H2>
17 <p>Suppose you have written a little set of functions
18 which you expect that other parts of your program
19 (or other parts of
<em>other
</em> people's programs)
21 And, so that it will be easier for you
23 to call the functions correctly,
24 suppose that you have written a header file
25 containing external prototype declarations for the functions.
27 suppose that the prototypes look like this:
30 extern double f2(int, double);
31 extern int f3(int, FILE *);
33 You might put these three declaration in a file called
<TT>funcs.h
</TT>.
35 we don't need to worry about
36 what these three functions
41 that
<TT>f3
</TT> obviously reads from or writes to
42 a
<TT>FILE *
</TT> stdio stream.
43 </p><p>Now, suppose that you have a source file
44 containing a function which calls
<TT>f1
</TT> and/or
<TT>f2
</TT>.
45 At the top of that source file,
46 you would put the line
52 the compiler would get down to the line
54 extern int f3(int, FILE *);
56 within
<TT>funcs.h
</TT> and complain,
57 because it would not know what a
<TT>FILE
</TT> is
58 and so would not know how to think about
59 a function that accepts a pointer to one.
60 If the calling program
61 (that is, the source file that included
<TT>"funcs.h"</TT>)
62 didn't call
<TT>f3
</TT> or
<TT>printf
</TT> or
<TT>fopen
</TT>
63 or any of the other stdio functions,
64 it would have no reason to include
<TT><stdio.h
></TT>,
65 and
<TT>FILE
</TT> would remain undefined.
66 (If, on the other hand,
67 the source file in question did happen to include
<TT><stdio.h
></TT>,
68 and if it included it before it included
<TT>"funcs.h"</TT>,
69 there would be no problem.)
70 </p><p>What's the right thing to do here?
71 We could say that anyone who included
<TT>"funcs.h"</TT>
72 always had to include
<TT><stdio.h
></TT>, first.
73 But you can think of header files a little bit like you think of functions:
74 it's nice if they're ``black boxes'',
75 if you don't have to worry about what's inside them,
76 if you don't have to worry about including them in a certain order.
77 </p><p>Another way to think about the situation is this:
78 since the prototype for
<TT>f3
</TT> inside of
<TT>funcs.h
</TT>
80 maybe we should put the line
82 #include
<stdio.h
>
84 right there at the top of
<TT>funcs.h
</TT>!
86 Can the preprocessor handle
87 seeing an
<TT>#include
</TT> directive
88 when it's already in the middle
89 of processing another
<TT>#include
</TT> directive?
90 The answer is that yes, it can;
92 (that is,
<TT>#include
</TT> directives)
94 (They may be nested up to a depth of at least
8,
95 although many compilers probably allow more.)
96 Once
<TT>funcs.h
</TT> takes care of its own needs,
97 by including
<TT><stdio.h
></TT> itself,
98 the eventual top-level file
99 (that is, the one you compile,
100 the one that includes
<TT>"funcs.h"</TT>)
101 won't get error messages about
<TT>FILE
</TT> being undefined,
102 and won't have to worry about
103 whether it includes
<TT><stdio.h
></TT> or not.
105 What if the top-level source file
106 <em>does
</em> include
<TT><stdio.h
></TT>?
107 Now
<TT><stdio.h
></TT> will end up being processed twice,
108 once when the top-level source file asks for it,
109 and once when
<TT>funcs.h
</TT> asks for it.
110 Will everything work correctly
111 if
<TT><stdio.h
></TT> is included twice?
112 Again, the answer is yes;
113 the Standard requires that the standard header files
114 protect themselves against multiple inclusion.
115 </p><p>It's good that the standard header files are protected in this way.
116 But how do they protect themselves?
117 Suppose that we'd like to protect our own header files
118 (such as
<TT>funcs.h
</TT>)
119 in the same sort of way.
121 </p><p>Here's the usual trick.
122 We rewrite
<TT>funcs.h
</TT> like this:
127 #include
<stdio.h
>
130 extern double f2(int, double);
131 extern int f3(int, FILE *);
136 added the
<TT>#ifndef
</TT> and
<TT>#define
</TT> lines at the top,
137 and the
<TT>#ifndef
</TT> line at the bottom.
138 (The macro name
<TT>FUNCS_H
</TT> doesn't really mean anything,
139 it's just one we don't
145 its name mimic the name of the header file we're protecting.)
146 Now, here's what happens:
147 the first time the compiler processes
<TT>funcs.h
</TT>,
148 it comes across the line
152 and
<TT>FUNCS_H
</TT> is not defined,
154 The very next thing it does
155 is
<TT>#define
</TT>s the macro
<TT>FUNCS_H
</TT>
156 (with a replacement text of nothing, but that's okay,
157 because we're never going to expand
<TT>FUNCS_H
</TT>,
158 just test whether it's defined or not).
159 Then it processes the rest of
<TT>funcs.h
</TT>, as usual.
161 if that same run of the compiler ever
162 comes across
<TT>funcs.h
</TT> for a second time,
163 when it comes to the first
<TT>#ifndef FUNCS_H
</TT> line again,
164 <TT>FUNCS_H
</TT> <em>will
</em> at that point be defined,
165 so the preprocessor will skip down to the
<TT>#endif
</TT> line,
166 which will skip the whole header file.
167 Nothing in the file will be processed a second time.
168 </p><p>(You might wonder what would tend to go wrong
169 if a header file were processed multiple times.
171 multiple external declarations for the same function or global variable,
172 as long as they're all consistent,
173 so those wouldn't cause any problems.
174 And the preprocessor also isn't supposed to complain
175 if you
<TT>#define
</TT> a macro which is already defined,
176 as long as it has the same value,
178 the same replacement text.
179 But the compiler
<em>will
</em> complain
180 if you try to define a structure type you've already defined,
181 or a typedef you've already defined
182 (see section
18.1.6),
184 So the protection against multiple inclusion
185 is important in the general case.)
186 </p><p>When header files are protected against multiple inclusion
187 by the
<TT>#ifndef
</TT> trick,
188 then header files can include other files
189 to get the declarations and definitions they need,
190 and no errors will arise because one file forgot to
191 (or didn't know that it had to)
192 include one header before another,
193 and no multiple-definition errors will arise because of multiple inclusion.
194 I recommend this technique.
195 </p><p>In closing, though,
196 I might mention that this technique is
197 somewhat controversial.
198 When header files include other header files,
199 it can be hard to track down the chain of who includes what
200 and who defines what,
201 if for some reason you need to know.
203 some style guides disallow nested header files.
204 (I don't know how these style guides recommend that you
205 address the issue of having to require
206 that certain files be included before others.)
210 <a href=
"sx6a.html" rev=precedes
>prev
</a>
211 <a href=
"sx7.html" rel=precedes
>next
</a>
212 <a href=
"sx6.html" rev=subdocument
>up
</a>
213 <a href=
"top.html">top
</a>
216 This page by
<a href=
"http://www.eskimo.com/~scs/">Steve Summit
</a>
217 //
<a href=
"copyright.html">Copyright
</a> 1996-
1999
218 //
<a href=
"mailto:scs@eskimo.com">mail feedback
</a>