使编译器允许 <a.h> 而不是"a.h"

Make compiler allow <a.h> instead of "a.h"

本文关键字:编译器 gt lt      更新时间:2023-10-16

我有一个第三方库,我想包含在我的代码中,但开发人员通过<>语法包含了所有本地头文件,导致编译时发生"没有这样的文件或目录"错误。

如果我手动更改#include <a.h>#include "a.h"有问题的文件编译就可以了。唯一的问题是,有数百个文件通过<>包含所有类型的标头。

是否有 UNIX 编译器指令将找不到的<>视为"?

溶液:

在尝试了几件事之后,我最终使用 sed 将所有#include <XXX.h>替换为#include "XXX.h".以下是为整个目录更改它的命令:

find ./ -type f -exec sed -i -E "s/include <(.+).h>/include "1.h"/g" {} ;

这适用于我的具体情况。我不建议将所有标题包含替换为"。

同时在 C\C++ 程序中包含头文件(或库)。有两种方法可以执行此操作:

1). 用引号写文件名(如#include "a.h")
2).将文件名写在尖括号中(如#include<a.h>)

但是两者都不同,第一种方法#include"a.h"首先搜索程序当前目录中的文件,然后在C++库中搜索。另一方面,如果文件存在,#include<a.h>只会在默认的C++库中查找,其他明智的编译器会给出错误。

我认为在您的情况下,"a.h"文件位于程序的当前目录中,这就是#include"a.h"工作而<a.h>不起作用的原因。如果你想要这样,只需复制文件并将其粘贴到编译器的目录中,其他内置头文件所在的目录中。 您只需在资源管理器中搜索"stdio.h",然后打开包含文件的文件夹并将"a.h"粘贴到该文件夹中。然后尝试使用#include<a.h>它会正常工作。 我希望这能回答这个问题。

正式地,C11标准(ISO/IEC 9899:2011)说:

6.10.2 源文件包含

2 表单的预处理指令

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

在实现定义的位置序列中搜索由<>分隔符之间的指定序列唯一标识的标头,并导致替换该标头 指令由标头的全部内容。如何指定地点或标题 标识是实现定义的。

3 表单的预处理指令

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

导致该指令被标识的源文件的全部内容替换 按"分隔符之间的指定顺序。搜索命名源文件 以实现定义的方式。如果不支持此搜索,或者如果搜索 失败,指令被重新处理,就好像它读取一样

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

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

因此,<header.h>表示法会导致预处理器以实现定义的方式搜索标头。"header.h"表示法使预处理器以可能不同的实现定义方式搜索标头,如果该搜索失败,则它使用与用于<header.h>相同的搜索进行搜索。

因此,引用的表示法在比尖括号表示法更少的位置看起来 - 但尖括号表示法可能比引用的符号在更少的位置。

对于许多编译器(预处理器),-I选项指定要搜索标头的额外位置(目录)。 这些地点通常在默认位置之前搜索。 此外,预处理器通常会在当前目录或包含源文件的目录中查找标头,或查找嵌套#include操作的当前头文件,或两者兼而有之。 出于向后兼容性的原因,规则通常有点复杂。

例如,c99编译器的 POSIX 规范说:

-Idirectory

更改搜索名称不是绝对路径名的标头的算法,以便在查找常用位置之前在由目录路径名命名的目录中查找。因此,名称用双引号括起来的标头("")应首先在带有#include行的文件目录中搜索,然后在-I选项中命名的目录中搜索,最后在通常的位置搜索。对于名称用尖括号(<>)括起来的标头,应仅在-I选项中命名的目录中搜索标头,然后在通常的位置搜索。-I选项中指定的目录应按指定的顺序进行搜索。如果使用-I选项指定默认情况下搜索的常用位置之一的目录,则未指定结果。实现应在单个c99命令调用中支持此选项的至少十个实例。

Microsoft将有自己的这些规则版本。


要解决问题中的问题,您需要将符号从#include <a.h>更改为#include "a.h",或者您需要将标头安装在无论如何都可以找到它的目录中(例如/usr/local/include在许多类Unix系统上)。 如果两者都不能接受,则需要在编译器命令行上指定存储a.h的目录 - 例如,在基于 Unix 的系统上使用-I.

可能有一种方法可以将编译器配置为在不需要命令行选项的情况下查找额外的目录。 不过,这些技术非常依赖于编译器。 应更改使用的表示法(尖括号改为引号)或将该选项添加到编译器命令行。