本地包含路径隐藏系统头文件

gcc: local include path hides system header file

本文关键字:系统 文件 隐藏 路径 包含      更新时间:2023-10-16

我有一个本地文件endian.h,它声明了一些字节交换函数。

#pragma once
#include <cstdint>
inline uint16_t bswap(uint16_t val) { return __builtin_bswap16(val); }
inline uint32_t bswap(uint32_t val) { return __builtin_bswap32(val); }
...

似乎包含路径CMake生成在我的makefiles导致/usr/include/endian.h/usr/include/ctype.h隐藏,而不是解析到./src/foo/endian.h

In file included from /usr/include/ctype.h:39:0,
                 from /usr/include/c++/5/cctype:42,
                 ...
                 from ./src/foo/session.h:3
./endian.h: In function ‘uint32_t bswap(uint32_t)’:
./endian.h:17:36: error: conflicting declaration of C function ‘uint32_t bswap(uint32_t)’
  inline uint32_t bswap(uint32_t val) { return __builtin_bswap32(val); }

其中一个包含路径是当前目录,与endian.h文件所在的目录相同:-I ./src/foo

是这个路径导致/usr/include/endian.h被隐藏

:

g++ -I./src ./src/foo/session.cpp

破碎:

g++ -I./src -I./src/foo ./src/foo/session.cpp

我有一个(明显错误的)印象,尖括号包括搜索系统路径,而引号包括搜索使用-I指定的路径。

包含路径-I./src,如果我#include "bar/bar.h"./src/foo/foo.h,工作,即使它不是本地的foo子目录(即:它找到bar/bar.h使用-I./src包含路径),我想这解释了我的印象关于什么每个包含类型的意思。

然而,这些似乎也会影响如何找到系统包含(或者至少,如何找到尖括号包含)。对吗?

不强迫我重命名我的本地endian.h文件,是唯一的方法来解决这个问题,以删除该包含路径?

以下是gcc手册中关于include搜索顺序的说明:

查找顺序如下:

  1. 对于include指令的quote形式,首先搜索当前文件的目录。
  2. 对于include指令的引用形式,由-iquote选项指定的目录将按照从左到右的顺序搜索,如它们出现在命令行上。
  3. 使用-I选项指定的目录按从左到右的顺序扫描。
  4. 用- issystem选项指定的目录按从左到右的顺序扫描。
  5. 扫描标准系统目录
  6. 用- dirafter选项指定的目录按从左到右的顺序扫描。

可以看到,-I选项(3)包含的文件在标准系统目录(5)(其中包括/usr/include)之前搜索。

所以一般来说,你用-I添加的目录中的文件将隐藏同名的系统头文件,不管这些文件是包含在<>还是""中。

""<>之间的区别在于,"" 包含的文件首先搜索当前目录(以及-iquote目录,但这更加模糊)。因此,如果您包含一个像#include "foo/bar.h"这样的文件,并且该文件包含"endian.h",那么如果foo/endian.h存在,它将被使用,而不是来自标准包含目录的同名文件。但是,如果您使用#include <endian.h>,则将使用系统版本。通过这种方式,如果使用正确的引号,可以减少两个方向上的意外名称冲突。

最初确实存在""<>之间的区别。但是,目前,据我所知,所有主要的编译器都平等地对待这两者。就编译器如何处理它们而言,它们之间实际上没有区别。人们习惯使用这些符号。endian.h是一个标准标头,通用名称。你应该把它往下移动一个文件夹,以避免名称冲突,比如"myProject/endian.h",或者把名字改成一个更明确的。