[comp.lang.c] #include "filename.h" does not mean "include user file"

ned@pebbles.cad.mcc.com (Ned Nowotny) (03/16/90)

[ Note:  Followups are directed to comp.std.c.  GNU mailing list readers ]
[        should probably just take note.                                 ]

From K&R2, section A12.4, page 231:

        A control line of the form
	    #include <filename>
    causes the replacement of that line by the entire contents of the file
    _filename_.  The characters in the name _filename_ must not include >
    or newline, and the effect is undefined if it contains any of ", ', \,
    or /*.  The named file is searched for in a sequence of implementation-
    dependent places.
	Similarly, a control line of the form 
	    #include "filename"
    searches first in association with the original source file (a deliberately
    implementation dependent phrase), and if that search fails, then as in the
    first form.  The effect of using ', \, or /* in the filename remains
    undefined, but > is permitted.
	Finally, a directive of the form
	    #include token-sequence
    not matching one of the previous forms is interpreted by expanding the
    token sequence as for normal text; one of the two forms with <...> or
    "..." must result, and it is then treated as previously described.
	#include files may be nested.

I believe that this description is essentially equivalent to the version in
the current (as yet still unpublished) ANSI C standard.  Moreover, it is
essentially the same as (though more precise than) the description given in
K&R1.

In all cases, #include "filename" has never meant:

       If the file name is enclosed by a pair of quotation marks, the file
    is presumed to be a user-supplied header file.  The search to find it
    begins in the current directory.  If it is not found, then the predefined
    set of locations is examined.  The -I option also works with user-supplied
    header files.
                -- _C++ Primer_, Stanley B. Lippman, Copyright 1989, page 13

Nor does it have the meaning implied in the following passage from the _User's
Guide to GNU C++_, page 22, wherein the '-I-' flag to G++ is described:

    In addition, the '-I-' option inhibits the use of the current directory
    as the first search directory for '#include "file"'.  Therefore, the
    current directory is searched only if it is requested explicitly with
    '-I.'.  Specifying both '-I-' and '-I.' allows you to control precisely
    which directories are searched before the current one and which are
    searched after."

Neither of the previous two quotes should be construed as a complaint directed
specifically at either Mr. Lippman or Mr. Tiemann.  I have heard and read
similar descriptions of the behavior expected of the #include "filename"
construct many times before.  In fact, I myself once believed essentially the
same thing having failed to carefully read the appropriate passage in the
appendix of K&R1.  (Of course, if both Mr. Lippman and Mr. Tiemann meant that
the current directory referenced in their descriptions was the directory in
which the current file resides which contains the particular #include statement
to be processed, then their descriptions are correct, though confusing.
Generally, I find it more natural to think of the current directory as being
the one current when the compiler was invoked.)

For an example of the kind of problems which the above intuitive usage will
cause, consider the following:

    1)  A source file in the current directory which is being compiled to test
	the header file described next.
    2)  A copy in the current directory of a header file located in a project
        defined include directory.  This file contains some value which is to
	be varied for the purposes of testing; therefore, the copy is a
	temporary necessity.
    3)  The source file in 1 above includes a file from the project defined
	include directory which actually contains the include statement for
	the header file which has been copied and modified.

Given that '-I.' is one of the options passed to the compiler:

    If the include statement in the header file included by the source file in
    1 above is of the form #include <filename>, all is well.  The header file
    with the local changes will be picked up as expected.  However, if the form
    of the include statement is #include "filename", the compiler will ignore
    the copy of the header file in the current directory and silently pick up
    the original header file located in the project defined include directory.

As a result of problems similar to the one described above, it seems that
programmers should always use the #include <filename> form unless they
have a specific, well defined situation in which the behavior of the
#include "filename" form is clearly desired.  The #include "filename" form
seems most appropriate for associated source and header files which are
generated by code generating programs like YACC and LEX.  (Of course, if .
is not one of the implementation defined directories searched when the
#include <filename> form is used, '-I.' must be passed on the compiler
command line.  If fact, . will almost certainly not be one of the standard
search directories for the #include "filename" form either.  If it seems to
have behaved that way, it is most likely because the header files included
were in the same directory as the source files which happened to be in the
current directory during compilation.)

Ned Nowotny, MCC CAD Program, Box 200195, Austin, TX  78720  Ph: (512) 338-3715
ARPA: ned@mcc.com                   UUCP: ...!cs.utexas.edu!milano!cadillac!ned
-------------------------------------------------------------------------------
"We have ways to make you scream." - Intel advertisement in the June 1989 DDJ.

shap@delrey.sgi.com (Jonathan Shapiro) (03/17/90)

In article <6928@cadillac.CAD.MCC.COM> ned@MCC.COM (Ned Nowotny) writes:
>[ Note:  Followups are directed to comp.std.c.  GNU mailing list readers ]
>[        should probably just take note.                                 ]
>
[ Discussion of meaning of #include "file" ellided... ]

To preclude the rash of corrections, the issue is well known.  Early
cpp specs didn't specify whether the "file" syntax meant relative to
the file that did the include or relative to the source file.  The cpp
by Jon Reiser (sp?) implemented the former, when the latter was the
intended meaning.

Reiser's preprocessor has spread and a few very strange folks have
come to depend on the behavior.

In any case, it is well understood.

Jon