简体   繁体   中英

Is there any standard requirement for C++ #include lookup?

Recently I learned that gnu cpp and msvc cl treat #include files differently. The common behavior is to look inside the directory of next to the includ_ing_ file, and then iterate over the include path (which is obviously set using -I or /I compiler arguments.)

But now I wonder: did I learn correctly, or is there actually a standard for the preprocessor, too?

According to the standard, both #include <...> and #include "..." shall search an implementation defined set of places. There is not even a requirement that the name provided between <> or "" is a file name, just that it allows unique identification of a header.

Having said that, if an implementation wants to have any hope of compiling existing source, it had better follow the same conventions as the rest: <...> refers to a system include file, and "..." refers to your own include files (and the directory containing the source file should be searched first). None of these are requirements from the standard, but without them you have no way to compile pretty much any existing code out there.

The standard is a little schizophrenic in places - in one place it will give you tools to deal with files and directory (the filesystem extension in C++17), while in others it refuses to acknowledge that such things as files and directories even exist. Presumably this is because the authors do not want to mess with ancient text too much, since it works fine now and might just accidentally break stuff, but it does look a bit funny.

To expand on H. Gujit's answer, neither the C or C++ language standards provide any guarantees here, but the POSIX standard does provide some additional guarantees about how cpp (the C P re p rocessor) shall function. For instance, in the description of the -I command line option :

Thus, headers whose names are enclosed in double-quotes ( "" ) shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets ( " <> " ), the header shall be searched for only in directories named in -I options and then in the usual places.

So any UNIX-like platforms attempting POSIX compliance will behave in this way.

According to the standard (16.2 [cpp.include]/2), #include <...>

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters. How the places are specified or the header identified is implementation-defined. [emphasis added]

In contrast (16.2 [cpp.include]/3), #include "..."

causes the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters. The named source file is searched for in an implementation-defined manner. If this search is not supported, or if the search fails, the directive is reprocessed as if it read #include <...> with the identical contained sequence (including > characters, if any) from the original directive. [emphasis added]

So the locations and techniques are entirely implementation defined, except that #include "..." falls back on #include <...> if no source file is found in the initial search.

The difference in wording is important: #include <...> does not require a source file; it's entirely up to the implementation how it handles standard headers. User-written header files should only be pulled in with #include "..." , since that's the one that's required to handle source files.

For the most part, compilers implement these things in the way that you'd expect. The critical difference that you're seeing with MSVC is that for #include "..." it searches first in the directory of the top-level source file that's being compiled, while other compilers search first in the directory of the source file that's currently being compiled. This matters when a header file has a #include "..." directive: most compilers search in the directory where the header file lives, but MSVC searches as if the #include "..." directive was in the top-level source file. Both are valid, and there are arguments for both approaches, although I personally find searching the directory where the header lives more intuitive and easier to work with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM