📄 incl.970605.html
字号:
<!-- as quoted in <34B6E9B3F32B6D75.F4A71C0B5E37E4F9.567D2B9CD4E81C94@library-proxy.airnews.net> --><html><!-- Mirrored from c-faq.com/cpp/incl.970605.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:00:34 GMT --><head><title></title></head><body><p>[This is the second of a pair of articles I posted in 1997on the difference between <TT>#include ""</TT>and <TT>#include <></TT>,and strategies for using them.This article starts out by replying to John Winters,who had commented on<a href="incl.970507.html">the first one</a>.I have altered the text somewhat for this web page.]<p>From: scs@eskimo.com (Steve Summit)<br>Subject: Re: Quotes vs. angle brackets in #includes<br>Date: Thu, 5 Jun 1997 14:54:42 GMT<br>Message-ID: <EBB5F7.BEG@eskimo.com><br>Newsgroups: comp.lang.c,comp.unix.programmer <p>Several weeks ago, in <5kve70$t89@polo.demon.co.uk>, John Winters wrote:<br>> I find it hard to conceive of a justification for using angle<br>> brackets for your own header files...<p>Well, there was one described in <a href="incl.970507.html">the earlier article</a> of mine(part of which you quote below, and which I'll say more about).But that involved a somewhat obscure situation, and I think Imight even be prepared to justify the use of angle brackets forother than standard headers on more prosaic grounds, such as thatthey simply look better or send a different message. Doublequotes say ``These are local headers.'' Angle brackets say,``These are system headers.'' Where do library and third-partyheaders fall? Squarely in the middle. Two kinds of headerinclusion aren't really enough, but they're all C gives us.If you've got a shared or third-party header to <TT>#include</TT>, and youdon't want to make it look local, it's very tempting to put it inangle brackets (perhaps with a blank line separating it from the<em>really</em> standard headers up above). At least, <em>I've</em> beentempted to do so; in fact that's the way I tend to do it.<p>Now, it's true that you can certainly decide to use double quotesfor all library headers, and it's true that if you focus on theStandard, angle brackets don't just say ``These are systemheaders'', they say, ``These are Standard headers.'' So there aredefinitely arguments in favor of leaning strongly towards doublequotes for all but Standard headers, but there are also (I claim)some reasons -- which are at least decent, if not necessarilycompelling -- to lean towards angle brackets for some of yourless than purely local headers.<p>...<p>>> On the other hand, the problem as I've stated it only comes up if<br>>> you use double quotes. If you use angle brackets for the central<br>>> project header files (in particular, for nested inclusions of<br>>> central project header files), the preprocessor never starts at<br>>> the wrong ``current'' directory, but always traverses the search<br>>> path from the start again, and finds the one in your private<br>>> include directory, as you wanted, regardless.<br>><br>> Presumably you had some particular implementation in mind, but in<br>> general there is no reason to expect the behaviour which you describe.<p>The ``particular implementation'' I had in mind is none other thanUnix, along with at least half of the non-Unix compilers outthere which have followed the old Unix preprocessor's lead inhandling double quotes. The question is, if double quotes inan <TT>#include</TT> directive mean ``use the current directory'', whichcurrent directory is it? If the directory we were in when weinvoked the compiler and the directory containing the <TT>.c</TT> file arethe same, then there's little question. But what if the <TT>.c</TT> fileis not in what we would otherwise think of as ``the currentdirectory''? Worse, what if a <TT>.c</TT> file (in the current directory)includes a header file, which for whatever reason is not in thecurrent directory, and that header file contains an <TT>#include</TT>directive using double quotes? Many preprocessors, includingthe traditional Unix ones, take the position that ``the currentdirectory'' which is first searched by <TT>#include ""</TT> in that caseis <em>the directory containing the file containing the</em> <TT>#include</TT><em>directive</em>. (I know you know about this possibility, John, butevidently you haven't had to deal with some of its even moresurprising consequences.)<p>Why would you want this rule at all? Why not make ``the currentdirectory'' be unilaterally <em>the</em> current directory? The answeris that, at least some of the time, the Unix behavior is exactlywhat you want. Suppose I'm trying to share some code, but in aninformal way, neither as a library nor even as a precompiledobject file; suppose that I call (in my Makefile, projectdefinition, or other build procedure) for some <TT>.c</TT> file in someother directory to be compiled and the resulting object linkedinto my program. (Why am I compiling it myself, instead ofusing a precompiled object or library? Perhaps I need to compileit with my own set of macro definitions to pick a certain setof <TT>#ifdef</TT> groupings.) Suppose further that this source fileI'm trying to compile has, off in its own directory where I'mcompiling it from, its own header file which I don't otherwiseneed. The Unix behavior will then ``do the right thing'': thefile's header, which it includes using double quotes, will befound over in its directory.<p>Now, to be sure, there would have been other ways to skin thiscat. If the rule were that the current directory is always <em>the</em>current directory, such that the preprocessor was unable to findthe remote source file's header in this case, I could have addedthe remote file's directory to the list of directories to besearched for header files. But I assume that this is the sort ofcase that prompted the adoption of what I'm calling the ``Unix''preprocessor behavior, and programmers on large projects need tounderstand it, because many compilers have followed Unix's lead,but the rule does have, as I've said, some even more surprisingconsequences.<p>Suppose I'm working with several other people on a large project.Suppose we've got a central directory, <TT>/usr/project</TT>, containingthe project source code, and a subdirectory of central directory,<TT>/usr/project/include</TT>, containing all the shared project sourcefiles. (Perhaps we chose to place the header files in their owndirectory because they are shared between many of the librariesor modules which make up the project and which are distributedamong several other subdirectories of <TT>/usr/project</TT>.) Supposefurther that I have my own directory, <TT>/usr/scs/project</TT>, in whichI'm working on my own parts of the project prior to releasingthem to the central directory, and suppose that I've got asubdirectory <TT>/usr/scs/project/include</TT> containing any projectheader files which I'm modifying. Naturally, whenever I compilepart of the project, I'll arrange (using <TT>-I</TT> switches, if underUnix) that the directories <TT>/usr/scs/project/include</TT> and<TT>/usr/project/include</TT> be additionally searched for header files,and in that order.<p>Finally, suppose that there are two files <TT>project.h</TT> and<TT>types.h</TT> in <TT>/usr/project/include</TT>, and that <TT>project.h</TT> containsthe line<p><pre> #include "types.h"</pre><p>One day, I have occasion to make a change to <TT>types.h</TT>. I make acopy in <TT>/usr/scs/project/include</TT>, edit it, and then arrange torecompile (in my own directory) those parts of the project whichwill be affected by the change, which will probably be nearly allof them. When I come back from lunch, to try the recompiledproject out, I find that my changes to <TT>types.h</TT> have <em>not</em> takeneffect! Why not? Because whenever any of the project's <TT>.c</TT> filesincluded <TT>"project.h"</TT>, they found it in <TT>/usr/project/include</TT>,because I don't have my own local copy of <TT>project.h</TT>. But by therules of ``the current directory is the includer's directory,''when <TT>/usr/project/include/project.h</TT> asks for <TT>"types.h"</TT>, thefirst place to look is in <TT>/usr/project/include</TT>, so it finds<TT>/usr/project/include/types.h</TT>, <em>not</em> <TT>/usr/scs/project/include/types.h</TT>.To fix the problem (assuming I can even figure out what the heckis going on), I need to make a copy of <TT>project.h</TT> in<TT>/usr/scs/project/include</TT>, even though I have no intention ofmodifying it, just so that all compiles will find <em>it</em> first andso that <em>its</em> <TT>#include</TT> of <TT>"types.h"</TT> will find <em>my</em> modified copyof <TT>types.h</TT>. (Then, I go off for a long afternoon snack breakwhile I recompile the entire project, again.)<p>Now, this may sound like such a complicated, contrived, andobscure situation that it's not worth making implementationstrategy decisions on. I'd even be inclined to agree with you,except that Larry Weiss knew immediately and exactly what I wastalking about, so he's obviously run into this problem, too.(And I suspect that he and I are not alone.) When you findyourself in this situation, you have exactly 4 choices thatI can think of:<ol><p><li>Use a different compiler with a different set of rulesfor resolving <TT>#include ""</TT> lines.<p><li>Disallow ``nested #include files''; don't have <TT>project.h</TT>do an <TT>#include</TT> on <TT>types.h</TT> at all.<p><li>Always check out <TT>project.h</TT> (into your own, private workdirectory, that is) whenever you want to work on <TT>types.h</TT>,and accept some wasted compilation time when you forget.<p><li>Have <TT>project.h</TT> use<pre> #include <types.h></pre>instead, so that it always unambiguously finds the firstone in the header file search path, without tripping upon the question of what ``the current directory'' is.</ol><p>The last time this happened to me (for yes, as you may haveguessed, not all of these ``suppose'''s have been hypothetical)it occurred to me that <em>this</em> is a much stronger argument for aban on nested header files (i.e. choice #2) than the more usualbut much weaker argument of ``it makes it harder to find wherethings are defined,'' an argument which is truly convincing onlyto those who are still unclear on the concept of ``grep''. But ifyou're not willing to ban nested <TT>#include</TT> files, and if you'renot in a position to switch compilers, and if you're tired ofmassive recompilations (or, worse, of searching in vain for someother cause of a bug after your fix to a central header filedidn't seem to work), then #4 may be your best or only option,implementation-defined though it may be.<p>Heretical advice? Perhaps...<p><address><a href="http://www.eskimo.com/~scs/">Steve Summit</a><br><a href="mailto:scs@eskimo.com">scs@eskimo.com</a></address></body><!-- Mirrored from c-faq.com/cpp/incl.970605.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:00:34 GMT --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -