【问题标题】:path: valid or not in `#include`?路径:在 `#include` 中是否有效?
【发布时间】:2019-07-17 17:12:17
【问题描述】:

今天我读到了这个问题Any rules about underscores in filenames in C/C++?, 而且我发现该标准似乎不允许在许多库中通常看到的内容非常有趣(我也在我的个人库中这样做):

例如,在opencv 我们可以看到:

// File: opencv/include/opencv2/opencv.hpp

#include "opencv2/opencv_modules.hpp"

但是标准说:

§ 6.10.2 源文件包含

语义

5 实现应为序列提供唯一的映射 由一个或多个非数字或数字 (6.4.2.1) 后跟一个 句点 (.) 和一个非数字。第一个字符不得 一个数字。实现可能会忽略字母顺序的区别 大小写并将映射限制为之前的八个有效字符 期间。

nondigit 表示字母(A-Za-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] = '\0';
    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)。

  • 真的禁止在包含中使用相对路径吗?

【问题讨论】:

  • 不禁止使用/,但这样做的结果是实现定义的。几乎所有关于&lt;&gt; 之间或"" 之间的序列在#include 指令中都是实现定义的。该标准规定,如果您使用诸如abcdefgh.h 之类的名称,则需要实现将其作为唯一名称进行处理(不区分大小写且不使用数字代替a)。实现可能区分大小写;它可能允许其他字符——这些细节是实现定义的,这意味着实现必须记录它的规则。

标签: c path include filenames


【解决方案1】:

啊;该标准实际上是在谈论支持 C 编译器的文件系统的最小字符集。

“”(或 中的任何内容,首先进行一些预处理)根据正常的 C 规则被解析为字符串,并从那里传递给操作系统以对其进行任何操作。

当程序员在将路径写入头文件时忘记键入\\ 而不是“\”时,这会导致 Windows 上的编译器错误。在现代 Windows 上,我们可以只使用 '/' 并期望它可以工作,但在旧 Windows 或 DOS 上却不行。

为了更多乐趣,请尝试

#include "/dev/tty"

真的很不错。它希望您在编译时键入 C 代码。

【讨论】:

  • 但是,标准可能已经特别提到它是最低限度的,并且可以实现定义其他字符,但它似乎对此非常严格。
  • 当我读到它时,它甚至说实现可以进一步限制它,但不能扩展它。
  • @CacahueteFrito:你读它是因为“第一个字符可能不是数字吗?”不幸的是,这只是规范作者的糟糕写作。整个事情是设置允许的最小值,并且“不应是数字”修改前面的内容,对于最低限度的符合系统没有要求允许文件名的第一个字符是数字。
  • 是的,“第一个字符不得为数字”似乎是在施加限制。它似乎直接禁止“1.h”,尽管我知道的所有实现当然都会允许它。
【解决方案2】:

我会说它不是被禁止的,但不是推荐的,因为它在某些情况下不会编译。

例如:

  • 如果您将此目录克隆到您的根目录(这样您将拥有C:\test\)。
  • 如果您尝试在虚拟环境中在线运行它,您可能会遇到问题。

真的禁止在包含中使用路径吗?

不知道你的意思:相对路径是常用的,但使用绝对路径会很愚蠢。

【讨论】:

  • 已编辑。当然是相对路径。而对于../,它只是不必创建一个子目录并在那里包含,但当然在一个真正的库中它只会包含子目录,并且永远不会上升。
猜你喜欢
  • 2011-05-05
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
  • 2014-05-05
相关资源
最近更新 更多