【问题标题】:Does C Standard guarantee diagnostic message for #error directive?C 标准是否保证#error 指令的诊断消息?
【发布时间】:2015-02-11 11:36:54
【问题描述】:

我在理解 N1570 C11 草案中 5.1.1.3/1Diagnostics 子条款的语义时遇到了一些困难(强调我的):

如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的情况,则符合标准的实现应产生至少一个诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现定义。 在其他情况下无需生成诊断消息9

我知道其目的是排除(非约束)未定义的行为(因此无法诊断缓冲区溢出等),但 #error 指令呢?如6.10.5/1 错误指令

表单的预处理指令

# error pp-tokensopt换行

使实现生成诊断消息,其中包括指定的预处理标记序列。

这两个子条款不是互斥的吗?

有关其他参考,另请参阅DR#176

【问题讨论】:

  • 我认为其意图是#error 应该始终生成诊断消息,但在前面的条款中没有提到这一点。
  • IIRC Keith Thompson 说,错误指令是唯一需要实现来产生诊断的地方。
  • “不需要生产”不代表“不能生产”。
  • @remyabel:在这一点上,我认为“应生产”(5.1.1.3/1)意味着“需要符合要求的实施”,并且该子条款是规范性的。
  • @GrzegorzSzpetkowski 准确地说,“应该”在这种情况下实际上意味着“必须”

标签: c language-lawyer


【解决方案1】:

C99 比该 DR 建议的解决方案更进一步。他们不需要诊断,而是需要将其视为错误。

4.一致性

4 实现不能成功翻译预处理翻译单元 包含 #error 预处理指令,除非它是被跳过的组的一部分 有条件的包含。

现在,严格来说,也许你是对的,一个实现可以选择拒绝编译一个包含#error指令的程序而不发出诊断,声称5.1.1.3 允许它忽略#error 的语义。但是,在标准设置的范围内尽可能无用的实现可以轻松解决任何需要诊断的尝试:实现可以简单地转储完整的预处理器输出(包括#error 之后的任何内容) ),然后是“某处有错误”。因此,标准是否需要诊断实际上并不重要。实现没有理由不这样做,标准几乎不能强迫不情愿的实现者这样做。

【讨论】:

  • 当一个 C 源文件被成功翻译后,这意味着某处必须存在一个文件,该文件可能经过额外的处理,可用于生成可运行的程序。当编译失败时,标准是否说明了宇宙的状态?除非标准要求编译器确保在编译失败时不存在与预期输出文件类似的东西,否则我不确定强制失败意味着什么。
【解决方案2】:

作为委员会的成员,我们对此类问题的回答通常会以“仔细阅读标准......”这样的短语开头,这并不像听起来那么圆滑。使用的语言非常具体。考虑第一个子句

符合要求的实现应至少产生一个诊断 消息(以实现定义的方式标识)如果 预处理翻译单元或翻译单元包含一个 违反任何语法规则或约束,即使行为是 也明确指定为未定义或实现定义。 在其他情况下不需要生成诊断消息。9

此子句明确提及“违反任何语法规则或约束”。因此,格式良好的#error 指令不会触发此子句。因此它不适用,互斥是没有实际意义的。

还要注意最后一句,它说诊断“不需要产生”。 “不需要”一词并不意味着“不得”。它只是意味着实现可以选择是否针对其他条件(例如,样式问题)发出诊断。但同样,这整个子句与 #error 无关紧要

您的第二个引用简单地说明了实现必须为格式良好的#error 指令做什么。

【讨论】:

  • “这只是意味着实现可以选择是否发出诊断”。但是在#error 的情况下,诊断消息总是有义务的(好吧,除非它在例如#if 指令的错误条件下,但这与实施无关)。我并不是暗示“不需要产生”意味着“必须不产生”,而是“没有在其他情况下产生诊断消息的义务。”。我希望我的观点很清楚。
  • 是的,你是对的。但是,正如我所说,该句子是适用于语法违规的子句的一部分。绕着标准语转头可能会让人费解。尝试使用一些通信标准:)
  • 这个答案肯定不对。 “诊断消息不需要在其他情况下产生”的全部意义。是它适用于违反任何语法规则或约束的程序。一个典型的例子可能是int main(void) { 1 / 0; },它指定不需要诊断。 #error Hello / int main(void) { } 也没有违反任何语法规则或约束。
  • "need not" 并不意味着"must not"。但它仍然与“必须”或“应”互斥。正如您所说的那样,“不需要”意味着编译器确实可以选择是否在其他情况下发出诊断。 #error 的规则说编译器没有那个选项。这肯定是矛盾的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多