路径:在 `#include` 中是否有效?
path: valid or not in `#include`?
今天看了这个问题,
我发现非常有趣的是,该标准似乎不允许在许多库中常见的内容(我在我的个人库中也是这样做的):
例如,在opencv
中我们可以看到:
// File: opencv/include/opencv2/opencv.hpp
#include "opencv2/opencv_modules.hpp"
但是标准说:
§ 6.10.2 Source file inclusion
Semantics
5 The implementation shall provide unique mappings for sequences
consisting of one or more nondigits or digits (6.4.2.1) followed by a
period (.
) and a single nondigit. The first character shall not be
a digit. The implementation may ignore distinctions of alphabetical
case and restrict the mapping to eight significant characters before
the period.
nondigit
表示字母(A
-Z
a
-z
)和下划线_
.
它完全没有提到 /
这意味着禁止使用路径,更不用说文件名中的点或连字符了。
为了首先测试这个,我写了一个简单的程序,在同一目录 tst/
:
中有一个源文件 test.c
和一个头文件 _1.2-3~a.hh
// File: test.c
#include "./..//tst//./_1.2-3~a.hh"
int main(void)
{
char a [10] = "abcdefghi";
char b [5] = "qwert";
strncpy(b, a, 5 - 1);
printf("b: \"%c%c%c%c%c\"\n", b[0], b[1], b[2], b[3], b[4]);
/* printed: b: "abcdt" */
b[5 - 1] = '[=11=]';
printf("b: \"%c%c%c%c%c\"\n", b[0], b[1], b[2], b[3], b[4]);
/* printed: b: "abcd" */
return 0;
}
// File: _1.2-3~a.hh
#include <stdio.h>
#include <string.h>
我用这个选项编译的:$ gcc -std=c11 -pedantic-errors test.c -o tst
编译器没有抱怨(我有 gcc (Debian 8.2.0-8) 8.2.0
)。
- 真的禁止在包含中使用相对路径吗?
啊;该标准实际上是在谈论支持 C 编译器的文件系统的最小字符集。
"" 中的任何内容(或 <> 首先进行一些预处理)根据正常的 C 规则被解析为一个字符串,并从那里传递给 OS 以做任何它想做的事情。
当程序员在将路径写入头文件时忘记键入 \
而不是 '\' 时,这会导致 Windows 上的编译器错误。在现代 Windows 上,我们可以只使用 '/' 并期望它能工作,但在旧的 Windows 或 DOS 上它没有。
要获得更多乐趣,请尝试
#include "/dev/tty"
真的很不错。它要你在编译时键入 C 代码。
我会说它不被禁止但不被推荐,因为它在某些情况下不会编译。
例如:
- 如果您将此目录克隆到您的根目录中(那么您将拥有
C:\test\
)。
- 如果您尝试在在线虚拟环境中运行它,您可能会遇到问题。
Is it really forbidden to use a path in an include?
不清楚你的意思:相对路径是常用的,但使用绝对路径是愚蠢的。
今天看了这个问题
例如,在opencv
中我们可以看到:
// File: opencv/include/opencv2/opencv.hpp
#include "opencv2/opencv_modules.hpp"
但是标准说:
§ 6.10.2 Source file inclusion
Semantics
5 The implementation shall provide unique mappings for sequences consisting of one or more nondigits or digits (6.4.2.1) followed by a period (
.
) and a single nondigit. The first character shall not be a digit. The implementation may ignore distinctions of alphabetical case and restrict the mapping to eight significant characters before the period.
nondigit
表示字母(A
-Z
a
-z
)和下划线_
.
它完全没有提到 /
这意味着禁止使用路径,更不用说文件名中的点或连字符了。
为了首先测试这个,我写了一个简单的程序,在同一目录 tst/
:
test.c
和一个头文件 _1.2-3~a.hh
// File: test.c
#include "./..//tst//./_1.2-3~a.hh"
int main(void)
{
char a [10] = "abcdefghi";
char b [5] = "qwert";
strncpy(b, a, 5 - 1);
printf("b: \"%c%c%c%c%c\"\n", b[0], b[1], b[2], b[3], b[4]);
/* printed: b: "abcdt" */
b[5 - 1] = '[=11=]';
printf("b: \"%c%c%c%c%c\"\n", b[0], b[1], b[2], b[3], b[4]);
/* printed: b: "abcd" */
return 0;
}
// File: _1.2-3~a.hh
#include <stdio.h>
#include <string.h>
我用这个选项编译的:$ gcc -std=c11 -pedantic-errors test.c -o tst
编译器没有抱怨(我有 gcc (Debian 8.2.0-8) 8.2.0
)。
- 真的禁止在包含中使用相对路径吗?
啊;该标准实际上是在谈论支持 C 编译器的文件系统的最小字符集。
"" 中的任何内容(或 <> 首先进行一些预处理)根据正常的 C 规则被解析为一个字符串,并从那里传递给 OS 以做任何它想做的事情。
当程序员在将路径写入头文件时忘记键入 \
而不是 '\' 时,这会导致 Windows 上的编译器错误。在现代 Windows 上,我们可以只使用 '/' 并期望它能工作,但在旧的 Windows 或 DOS 上它没有。
要获得更多乐趣,请尝试
#include "/dev/tty"
真的很不错。它要你在编译时键入 C 代码。
我会说它不被禁止但不被推荐,因为它在某些情况下不会编译。
例如:
- 如果您将此目录克隆到您的根目录中(那么您将拥有
C:\test\
)。 - 如果您尝试在在线虚拟环境中运行它,您可能会遇到问题。
Is it really forbidden to use a path in an include?
不清楚你的意思:相对路径是常用的,但使用绝对路径是愚蠢的。