C - 我应该使用引号还是括号将 headers 包含在单独的目录中

C - Should I use quotes or brackets to include headers in a separate directory

我有一个包含 srcinclude 目录的项目。编译时,我通过 -I 选项(gcc -Iinclude ...)传递 include 目录。

我应该使用双引号 (") 还是尖括号 (<) 来包含我自己的 header 文件?


我试图寻找答案,发现这两个相互矛盾的陈述:

  1. 通过双引号包含 header 相对于 c 文件的文件。其他所有内容(包含路径中的 header 文件)都带有尖括号。 -> 因此使用尖括号
  2. 包括带尖括号的标准 header。其他所有内容都用双引号引起来。 -> 因此使用双引号

在我看来陈述2更清楚。当包含带双引号的文件时,最明显的是它是我自己的 header.


我应该使用引号或括号来包含我自己的 header 文件吗? The C standard allows both possibilities。那么最佳做法是什么?

考虑这个例子:

+- include/
|  |
|  \- header.h
|
+- src/
   |
   \- main.c

语句是说要么使用:

#include "../include/header.h"

gcc src/main.c

或:

#include <header.h>

gcc -Iinclude src/main.c

您决定使用哪种样式。我个人比较喜欢第二种。但更重要的是在整个项目中使用一致的风格。

共同约定是:

  • 对属于 C 实现或平台的 header 使用 < … >——header 在您的项目之外,例如 C 标准库、Unix 或 Windows headers 和 headers 通常为您的开发环境安装的库。
  • 使用 " … " 作为项目一部分的 header。

这不是完全由C标准决定的;这是一个普遍的做法。对于每个分隔符选择,编译器都有一个查找 header 的位置列表(搜索路径)。这些搜索路径通常是为了方便上述使用而设计的,但它们可以通过 command-line 开关、环境变量、系统设置、and/or 时进行的设置进行自定义(取决于您使用的编译器)构建编译器。

以下是 C 标准在 C 2018 6.10.2 中对它们的描述。第 2 段说:

A preprocessing directive of the form

# 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.

第 3 段说:

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.

注意两者之间的一些区别:

  • 括号形式的文本说它搜索一个 header 标识 唯一 。报价表的文本不包含“独特”一词。这表明括号中的所有 header 都应该彼此不同,如果它们是旨在避免歧义的设计系统的一部分,您可能会想到这一点。
  • 请注意,第一种形式“搜索一系列 implementation-defined 个位置。”这符合编译器具有搜索标准 headers 的位置列表。对于第二种形式,它使用“由指定序列标识的源文件”。这符合使用引号之间的文本作为文件系统中的路径。

标准中的这个文本非常宽松,都允许 implementation-defined 方法来识别文件,因此可以将其中一个扩展为与另一个相同(尽管看到编译器抱怨会很有趣括号中命名的 header 不是唯一的),并且编译器配置选项足够广泛,您可以在您的项目中以任何一种方式使用它们。但是,通常最好还是遵循惯例。