【问题标题】:C preprocessor: what is the rationale behind not allowing argument of the #include directive to begin with a digit?C 预处理器:不允许 #include 指令的参数以数字开头的原因是什么?
【发布时间】:2021-05-17 00:04:31
【问题描述】:

N2479 C17..C2x 工作草案 — 2020 年 2 月 5 日 ISO/IEC 9899:202x (E):

6.10.2 源文件包含

实现应为由一个或多个非数字或数字 (6.4.2.1) 后跟句点 (.) 和单个非数字组成的序列提供唯一映射。第一个字符不能是数字。

问题:不允许 #include 指令的参数 (char-sequence) 以数字开头的原因是什么?

额外的问题:编译器似乎不会在违反上述应要求时生成任何诊断消息(例如使用#include "1.h")。为什么?

UPD。后来我的同事回答:The first character shall not be a digit 只与unique mappings 相关。所以,标准被误解了。

【问题讨论】:

  • @EricPostpischil -- “第一个字符不能是数字”怎么样?
  • @adabsurdum:糟糕,错过了。
  • @pmor -- 只有违反语法规则和约束时才需要诊断;这两者都不是,因此不需要诊断。但是,由于违反了约束之外的“应”,它仍然是未定义的行为。
  • @adabsurdum:这里没有违反规则。该段没有说程序不能使用这样的序列。该段落只允许实现不唯一地映射它; “1.h”可以映射到与“foo.h”相同的标题。
  • @EricPostpischil -- 6.10.2 5 表示 h-char-sequenceq-char-sequence 的第一个字符“应不是数字。”使用 q-char-sequence "1.h" 违反了应该,因此它是 4 2 的未定义行为:"如果出现在外部的“应该”或“不应”要求的约束...." 也许实现没有为序列提供唯一的映射;也许它根本不提供。还是我误读了什么可怕的东西?

标签: c include language-lawyer c-preprocessor diagnostics


【解决方案1】:

问题:不允许#include 指令的参数(字符序列)以数字开头的原因是什么?

就其本身而言,“第一个字符不应是数字”这句话似乎是在说 C 程序不应使用数字作为标题名称中的第一个字符。但是,它在两个句子之间告诉我们 C 实现必须如何处理标头名称,并且在一个子句 6.10 中,它告诉我们实现如何处理 #include 指令。告诉我们标头名称语法的子句在 C 标准 6.4.7 中的不同位置,它提供 #include <1/a.h> 作为可能指令的示例(C 2018 6.4.7 4)。

所以我相信 6.10.2 5 的意图是提供实现质量保证,即不能直接使用不支持文件名基本部分中至少八个字符的文件系统来实现 C ,但您可以使用忽略大小写(根据其最后一句)或不支持以数字开头的名称的文件系统。虽然“第一个字符不能是数字”似乎是对 C 程序的禁止,但那是因为在没有限定的情况下将其放在单独的句子中是错误的;前两句应该类似于“实现应为由非数字 (6.4.2.1) 后跟零个或多个非数字或数字后跟句点 (.) 和单个非数字组成的序列提供唯一映射。”

(在 C 1990 中,此段落出现在 6.8.2 中,其中重要性要求仅针对六个字符。在 C 1999 中增加到八个,反映了更好的文件系统的流行。)

【讨论】:

  • 我发现this defect report 确实表明文件名必须以非数字开头的规定 6.10.2 5 应被解释为适用于唯一性保证。
  • 后来我的同事回答:The first character shall not be a digit 只与unique mappings 相关。似乎这个想法是为了实现最低限度的要求,需要满足这些要求才能实现跨所有(或几乎所有)操作系统的可移植性。但是,unique mappings 似乎还有改进的空间:如果你在 Windows 下尝试在msvc 中使用#include "con.h" 会发生什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
相关资源
最近更新 更多