C ++ #include语义 [英] C++ #include semantics

查看:78
本文介绍了C ++ #include语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是同一预处理指令的多个问题。

This is a multiple question for the same pre-processing instruction.

除了在MSDN中找到的信息:

Apart from the info found in the MSDN:

#include指令(C-C ++)

1。 a:两种表示法有什么区别?

1.b:所有编译器都以相同的方式实现它们吗?

1.c:什么时候使用<> ;,以及什么时候使用 (即,将一个或另一个用于头文件包含的条件是什么?)?

1.a: What are the differences between the two notations?
1.b: Do all compilers implement them the same way?
1.c: When would you use the <>, and when would you use the "" (i.e. what are the criteria you would use to use one or the other for a header include)?

我已经看到至少有两种书写方式,其中包括一个人的项目标头。
考虑到您至少有4种标头类型,即:

I've seen at least two ways of writing includes of one's project headers. Considering that you have at least 4 types of headers, that is:


  • 项目的专用标头?

  • 您的项目的标题,但是正在导出符号(因此也就是公共)

  • 您的模块链接到的另一个项目的标题

  • 编译器或标准库的标题

  • private headers of your project?
  • headers of your project, but which are exporting symbols (and thus, "public")
  • headers of another project your module links with
  • headers of a compiler or standard library

对于每种标题:

2.a:您使用<>或

2.b:您会只包括{TheProject / TheHeader.hpp}还是只包括{TheHeader.hpp}?

2.a: Would you use <> or "" ?
2.b: Would you include with {TheProject/TheHeader.hpp}, or with {TheHeader.hpp} only?

3.a:您是否在树状组织(即目录内的目录,而不是目录中的每个文件)中使用源和/或标题的项目? )以及优点/缺点是什么?

3.a: Do you work on project with sources and/or headers within a tree-like organisation (i.e., directories inside directories, as opposed to "every file in one directory") and what are the pros/cons?

推荐答案

阅读所有答案以及编译器文档后,我决定遵循

After reading all answers, as well as compiler documentation, I decided I would follow the following standard.

对于所有文件,无论是项目标头还是外部标头,请始终使用以下模式:

For all files, be them project headers or external headers, always use the pattern:

#include <namespace/header.hpp>

命名空间至少要深一个目录,以避免冲突。

The namespace being at least one directory deep, to avoid collision.

Of当然,这意味着应该在其中添加项目标题的项目目录被添加为默认包含标题。

Of course, this means that the project directory where the project headers are should be added as "default include header" to the makefile, too.

之所以这样做,是因为我找到了以下信息:

The reason for this choice is that I found the following information:

我将在下面给出答案

来源:

在第16.2节包含源文件中,我们可以看到:

In the section 16.2 Source file inclusion, we can read that:

一种形式的预处理指令

  #include <h-char-sequence> new-line

在实现定义的位置序列中搜索由<之间的指定序列唯一标识的标头。和>定界符,并导致该指令被标头的全部内容替换。

searches a sequence of implementation-defined places for a header identified uniquely by the specified sequence between the < and > delimiters, and causes the replacement of that directive by the entire contents of the header. How the places are specified or the header identified is implementation-defined.

这意味着#include< ...>

This means that #include <...> will search a file in an implementation defined manner.

然后,下一段:


格式

A preprocessing directive of the form

  #include "q-char-sequence" new-line

导致该指令被源文件的全部内容替换,该内容由 ;定界符。以实现定义的方式搜索命名的源文件。如果不支持此搜索,或者搜索失败,则伪指令将被重新处理,就像它读

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 <h-char-sequence> new-line

具有与原始指令相同的包含顺序(包括>字符,如果有)。

with the identical contained sequence (including > characters, if any) from the original directive.

这意味着#include ...将以实现定义的方式搜索文件,然后,如果找不到该文件,将进行另一次搜索,就好像它是#include< ...>

This means that #include "..." will search a file in an implementation defined manner and then, if the file is not found, will do another search as if it had been an #include <...>

结论是我们必须阅读编译器文档。

The conclusion is that we have to read the compilers documentation.

请注意,由于某种原因,在标准中,系统和系统之间没有区别。或图书馆标头或其他标头。唯一的区别似乎是#include< ...>似乎以标头为目标,而#include ...

Note that, for some reason, nowhere in the standards the difference is made between "system" or "library" headers or other headers. The only difference seem that #include <...> seems to target headers, while #include "..." seems to target source (at least, in the english wording).

来源:

  • http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx

预处理器按以下顺序搜索包含文件:

The preprocessor searches for include files in the following order:


  1. 与包含#include语句的文件位于同一目录中。

  2. 在任何先前打开的目录中,包含与打开文件相反的文件。搜索从最后打开的包含文件的目录开始,一直到最先打开的包含文件的目录继续。

  3. 沿着每个/ I编译器选项指定的路径。

  4. (*)沿着INCLUDE环境变量或开发环境默认值指定的路径包括。

  1. In the same directory as the file that contains the #include statement.
  2. In the directories of any previously opened include files in the reverse order in which they were opened. The search starts from the directory of the include file that was opened last and continues through the directory of the include file that was opened first.
  3. Along the path specified by each /I compiler option.
  4. (*) Along the paths specified by the INCLUDE environment variable or the development environment default includes.


# include< MyFile.hpp>


预处理器按以下顺序搜索包含文件:

#include <MyFile.hpp>

The preprocessor searches for include files in the following order:


  1. 沿着路径

  2. (*)沿着INCLUDE环境变量或开发环境默认值指定的路径包括。


有关最后一步的说明


文档尚不清楚沿INCLUDE环境变量指定的路径 < ...> ... 都包含。以下引用使其符合标准:

Note about the last step

The document is not clear about the "Along the paths specified by the INCLUDE environment variable" part for both <...> and "..." includes. The following quote makes it stick with the standard:


对于指定为#include path-spec的包含文件,目录搜索从目录开始父文件,然后遍历任何祖父母文件的目录。也就是说,搜索从相对于包含源文件的目录开始,该目录包含正在处理的#include指令。如果没有祖父母文件且未找到该文件,则继续搜索,就像文件名放在尖括号中一样。

For include files that are specified as #include "path-spec", directory searching begins with the directory of the parent file and then proceeds through the directories of any grandparent files. That is, searching begins relative to the directory that contains the source file that contains the #include directive that's being processed. If there is no grandparent file and the file has not been found, the search continues as if the file name were enclosed in angle brackets.

最后一步(用星号标记)因此是阅读整个文档的一种解释。

The last step (marked by an asterisk) is thus an interpretation from reading the whole document.

来源:

  • https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
  • https://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html
  • https://gcc.gnu.org/onlinedocs/cpp/Include-Operation.html
  • https://gcc.gnu.org/onlinedocs/cpp/Invocation.html
  • https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html
  • https://gcc.gnu.org/onlinedocs/cpp/Once-Only-Headers.html
  • https://gcc.gnu.org/onlinedocs/cpp/Wrapper-Headers.html
  • https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html

以下引言概述了该过程:

The following quote summarizes the process:


GCC [...]将查找使用#include < file>请求的标头。 在[系统目录]中[...]在默认目录之前,按从左到右的顺序搜索-I命名的所有目录

GCC [...] will look for headers requested with #include <file> in [system directories] [...] All the directories named by -I are searched, in left-to-right order, before the default directories

GCC寻找带有#include file的请求标头。首先在包含-iquote选项所指定的目录中,然后在相同的位置查找带有尖括号的请求标头。

GCC looks for headers requested with #include "file" first in the directory containing the current file, then in the directories as specified by -iquote options, then in the same places it would have looked for a header requested with angle brackets.


#include MyFile.hpp


此变体用于您自己程序的头文件。预处理程序按以下顺序搜索包含文件:

#include "MyFile.hpp"

This variant is used for header files of your own program. The preprocessor searches for include files in the following order:


  1. 与包含#include语句的文件位于同一目录中。

  2. 沿着每个-iquote编译器选项指定的路径。

  3. 至于#include < MyFile.hpp>

  1. In the same directory as the file that contains the #include statement.
  2. Along the path specified by each -iquote compiler option.
  3. As for the #include <MyFile.hpp>


#include< MyFile.hpp>


此变体用于系统头文件。预处理程序按以下顺序搜索包含文件:

#include <MyFile.hpp>

This variant is used for system header files. The preprocessor searches for include files in the following order:


  1. 沿着每个-I编译器选项指定的路径。

  2. 在系统目录内。


1.d Oracle / Sun Studio CC


来源:

1.d Oracle/Sun Studio CC

Source:

  • http://docs.oracle.com/cd/E19205-01/819-5265/bjadq/index.html

注意该文本本身有些矛盾(请参见示例以了解)。关键短语是: 区别在于,仅在当前目录中搜索您的名称用引号引起来的头文件。

Note that the text contradict itself somewhat (see the example to understand). The key phrase is: "The difference is that the current directory is searched only for header files whose names you have enclosed in quotation marks."

此变体用于您自己程序的头文件。预处理程序按以下顺序搜索包含文件:

This variant is used for header files of your own program. The preprocessor searches for include files in the following order:


  1. 当前目录(即包含包含文件的目录)

  2. 以-I选项命名的目录(如果有的话)

  3. 系统目录(例如/ usr / include目录)


#include< MyFile.hpp>


此变体用于系统头文件。预处理程序按以下顺序搜索包含文件:

#include <MyFile.hpp>

This variant is used for system header files. The preprocessor searches for include files in the following order:


  1. 以-I选项命名的目录(如果有的话)

  2. 系统目录(例如/ usr / include目录)


1.e XL C / C ++编译器参考-IBM / AIX


来源:

1.e XL C/C++ Compiler Reference - IBM/AIX

Source:

  • http://www.bluefern.canterbury.ac.nz/ucsc%20userdocs/forucscwebsite/c/aix/compiler.pdf
  • http://www-01.ibm.com/support/docview.wss?uid=swg27024204&aid=1

这两个文件的标题都为 XL C / C ++编译器参考第一个文档较旧(8.0),但更易于理解。第二个是较新的版本(12.1),但是解密起来有点困难。

Both documents are titled "XL C/C++ Compiler Reference" The first document is older (8.0), but is easier to understand. The second is newer (12.1), but is a bit more difficult to decrypt.

用于您自己程序的头文件。预处理程序按以下顺序搜索包含文件:

This variant is used for header files of your own program. The preprocessor searches for include files in the following order:


  1. 当前目录(即包含包含文件的目录)

  2. 以-I选项命名的目录(如果有的话)

  3. 系统目录(例如/ usr / vac [cpp] / include或/ usr / include目录)


#include< MyFile.hpp>


此变体用于系统头文件。预处理程序按以下顺序搜索包含文件:

#include <MyFile.hpp>

This variant is used for system header files. The preprocessor searches for include files in the following order:


  1. 以-I选项命名的目录(如果有的话)

  2. 系统目录(例如/ usr / vac [cpp] / include或/ usr / include目录)


1.e结论


模式可能会导致各个编译器之间出现细微的编译错误,并且由于我目前同时在Windows Visual C ++,Linux g ++,Oracle / Solaris CC和AIX XL上工作,所以这是不可接受的。

1.e Conclusion

The pattern "" could lead to subtle compilation error across compilers, and as I currently work both on Windows Visual C++, Linux g++, Oracle/Solaris CC and AIX XL, this is not acceptable.

无论如何, 的优点无论如何,所描述的功能都不是很有趣,所以...

Anyway, the advantage of "" described features are far from interesting anyway, so...

我在工作中看到的(这不是理论,这是现实的,痛苦的专业经验

I saw at work (i.e. this is not theory, this is real-life, painful professional experience) two headers with the same name, one in the local project directory, and the other in the global include.

正如我们在使用时所使用的标题一样,标题都在本地项目目录中,而另一个在全局项目中。模式,并且该文件同时包含在本地头文件和全局头文件中,当出现奇怪的错误时,没有办法了解真正的情况。

As we were using the "" pattern, and that file was included both in local headers and global headers, there was no way to understand what was really going on, when strange errors appeared.

在包含文件中使用目录之所以节省了我们的时间,是因为用户不得不写:

Using the directory in the include would have saved us time because the user would have had to either write:

#include <MyLocalProject/Header.hpp>

#include <GlobalInclude/Header.hpp>

您会注意到,虽然

#include "Header.hpp"

将成功编译,因此仍然隐藏了问题,而

would have compiled successfully, thus, still hiding the problem, whereas

#include <Header.hpp>

在正常情况下不会进行编译。

would not have compiled in normal circonstances.

因此,坚持使用< ;>标记对于开发人员来说是强制性的,必须在正确的目录中包含include的前缀,这是首选<>

Thus, sticking to the <> notation would have made mandatory for the developer the prefixing of the include with the right directory, another reason to prefer <> to "".

同时使用<>符号和命名空间符号一起从预编译器中消除了猜测文件的可能性,而仅搜索默认的包含目录。

Using both the <> notation and namespaced notation together removes from the pre-compiler the possibility to guess for files, instead searching only the default include directories.

当然,仍然像往常一样包含标准库,即是:

Of course, the standard libraries are still included as usual, that is:

#include <cstdlib>
#include <vector>

这篇关于C ++ #include语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆