![]() |
|
|
|
#1 |
|
Posts: n/a
|
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. -- Derrick Coetzee |
|
|
|
#2 |
|
Posts: n/a
|
Derrick Coetzee wrote:
> 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. <snip> > Does anyone have a reasonable justification for the standard include > order that I haven't thought of? Already answered. HTH -- Morris Dovey West Des Moines, Iowa USA C links at http://www.iedu.com/c Read my lips: The apple doesn't fall far from the tree. |
|
|
|
#3 |
|
Posts: n/a
|
In article <Pine.LNX.4.44.0311182138520.14795->,
Derrick Coetzee <> wrote: >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... -- Rouben Rostamian |
|
|
|
#4 |
|
Posts: n/a
|
Morris Dovey wrote:
>> 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. 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 )-: -- Morris Dovey West Des Moines, Iowa USA C links at http://www.iedu.com/c Read my lips: The apple doesn't fall far from the tree. |
|
|
|
#5 |
|
Posts: n/a
|
[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 Coetzee wrote: > 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. -- Richard Heathfield : "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton |
|
|
|
#6 |
|
Posts: n/a
|
> 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. |
|
|
|
#7 |
|
Posts: n/a
|
On Tue, 18 Nov 2003, Derrick Coetzee wrote:
> 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? |
|
|
|
#8 |
|
Posts: n/a
|
In <kpBub.610$> Morris Dovey <> writes:
>Derrick Coetzee wrote: > >> 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... Then, your headers should include the system headers they need. I couldn't agree more with the OP on this point. >> 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. 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 -- Dan Pop DESY Zeuthen, RZ group Email: |
|
|
|
#9 |
|
Posts: n/a
|
In <Pine.LNX.4.44.0311182138520.14795-> Derrick Coetzee <> writes:
>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 <stddef.h> must be documented as a prerequisite. I agree that this is not the right way of defining hello.h, *these days*. >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 -- Dan Pop DESY Zeuthen, RZ group Email: |
|
|
|
#10 |
|
Posts: n/a
|
Dan Pop wrote:
> Morris Dovey wrote: >>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. Me too. It /does/ look as if I'd have done better to turn off the computer and get some sleep. Apologies to Derrick. >>/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. 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... -- Morris Dovey West Des Moines, Iowa USA C links at http://www.iedu.com/c Read my lips: The apple doesn't fall far from the tree. |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Kodak Easyshare - manual order probs | John Bailey | General Help Related Topics | 0 | 01-08-2009 03:37 PM |
| Why are TV shows on DVD Out Of Order? | mhadley | DVD Video | 3 | 09-20-2007 10:56 PM |
| DVD Verdict reviews: LAW AND ORDER: SPECIAL VICTIMS UNIT: THE FIFTH YEAR and more! | DVD Verdict | DVD Video | 0 | 11-03-2004 09:12 AM |
| Viewing order for Batman: The Animated Series? | Robert Kaiser | DVD Video | 11 | 07-25-2004 02:15 AM |
| New Releases: Apprentice, Magnum, Munsters & Law & Order: Updated complete downloadable R1 DVD DB & info lists | Doug MacLean | DVD Video | 1 | 06-05-2004 02:04 PM |