* better
[mascara-docs.git] / lang / C / the.ansi.c.programming.language / c.programming.notes.int / sx6b.html
blobe0fd85d877bef77b5857110bf645d78d2ba397ad
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. -->
5 <html>
6 <head>
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>
13 </head>
14 <body>
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)
20 will call.
21 And, so that it will be easier for you
22 (and them)
23 to call the functions correctly,
24 suppose that you have written a header file
25 containing external prototype declarations for the functions.
26 And,
27 suppose that the prototypes look like this:
28 <pre>
29 extern int f1(int);
30 extern double f2(int, double);
31 extern int f3(int, FILE *);
32 </pre>
33 You might put these three declaration in a file called <TT>funcs.h</TT>.
34 </p><p>For now,
35 we don't need to worry about
36 what these three functions
37 might
38 do,
39 other than
40 to notice
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
47 <pre>
48 #include "funcs.h"
49 </pre>
50 However,
51 if you were unlucky,
52 the compiler would get down to the line
53 <pre>
54 extern int f3(int, FILE *);
55 </pre>
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>&lt;stdio.h&gt;</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>&lt;stdio.h&gt;</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>&lt;stdio.h&gt;</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>
79 needs stdio.h,
80 maybe we should put the line
81 <pre>
82 #include &lt;stdio.h&gt;
83 </pre>
84 right there at the top of <TT>funcs.h</TT>!
85 Is that legal?
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;
91 header files
92 (that is, <TT>#include</TT> directives)
93 may be nested.
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>&lt;stdio.h&gt;</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>&lt;stdio.h&gt;</TT> or not.
104 </p><p>Or will it?
105 What if the top-level source file
106 <em>does</em> include <TT>&lt;stdio.h&gt;</TT>?
107 Now <TT>&lt;stdio.h&gt;</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>&lt;stdio.h&gt;</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.
120 How would we do it?
121 </p><p>Here's the usual trick.
122 We rewrite <TT>funcs.h</TT> like this:
123 <pre>
124 #ifndef FUNCS_H
125 #define FUNCS_H
127 #include &lt;stdio.h&gt;
129 extern int f1(int);
130 extern double f2(int, double);
131 extern int f3(int, FILE *);
133 #endif
134 </pre>
135 All we've done is
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
140 and won't
141 use anywhere else,
142 so we
143 use the convention
144 of having
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
149 <pre>
150 #ifndef FUNCS_H
151 </pre>
152 and <TT>FUNCS_H</TT> is not defined,
153 so it proceeds.
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.
160 But,
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.
170 It's okay to issue
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,
177 that is,
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),
183 etc.
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.
202 Therefore,
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.)
207 </p><hr>
209 Read sequentially:
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>
214 </p>
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>
219 </p>
220 </body>
221 </html>