【问题标题】:Why is using an identifier not in scope UB and not an error为什么使用不在 UB 范围内的标识符而不是错误
【发布时间】:2017-03-02 04:23:16
【问题描述】:

我在所有未定义行为列表中引用了 ANSI_ISO+9899-1990 -

  • 使用了在当前范围内不可见的标识符

为什么使用未定义的变量 UB 而不是错误?我想知道这背后的原因?将所有不“正确”的东西都设置为 UB 是否有效?

我知道大多数编译器都将其视为错误。但是为什么标准会这样说呢?

或者标准中没有“错误”的概念? c的语法是.*但是有一部分有UB?

【问题讨论】:

  • 阅读技术标准时,必须将规范性文本与信息性文本分开。必须遵循的规范性文本,而信息性文本仅用于澄清。引用的文本来自信息性附录。它不是规范性文本,也不是编译器必须遵循的。

标签: c language-lawyer undefined-behavior c89


【解决方案1】:

不,标准中有很多错误的概念,只是并非所有内容都算作错误。我先说两件事,这可能会对你有所帮助:

  1. C89/90 是为了编纂现有实践,不是创建新语言。这意味着有时有必要在某些事情上做出妥协,即使它们没有意义。

  2. C99+ 没有有这个限制,所以某些东西可以被清理。事实上,由于您引用的文本在 C99 中似乎消失了,这很可能是清理后的事情之一。

回到推理,ANSI C89 基本原理文档有这样的说法:

争议的一个来源是具有外部链接的标识符是否应该具有文件范围,即使在块中引入。基础文档在这一点上含糊其辞,不同的实现有不同的解释。例如,以下片段在文件范围方案中有效,而在块范围方案中无效:

typedef struct data d_struct ;
first(){
    extern d_struct func();
    /* ...  */
}
second(){
    d_struct n = func();
}

虽然普遍认为一旦超出范围就利用外部声明是不好的做法,但有些人认为翻译人员无论如何都必须记住声明以进行检查,那么为什么不承认这一点呢? 所采用的折衷方案基本上是规定块范围规则适用,但符合要求的实现不需要诊断重新声明超出范围的外部标识符失败(未定义行为)。

几乎可以肯定的是,“不同的实现有不同的解释”这句话导致他们将其标记为 UB 而不是错误。请注意,这里所讨论的不是 范围,而是实现是否需要报告您尝试使用它的事实。

【讨论】:

  • 好的,外部链接的范围似乎仍有争议,我同意这一点。但是为什么使用未定义的变量(通常是标识符)不属于错误?难道这只是他们当时做出的妥协之一。知道它没有出现在 C99 中令人欣慰。我没有副本。
  • 非常感谢您的链接。我一定会为它们添加书签。
  • @AjayBrahmakshatriya 还有其他来源,但这两个来源每个段落都有内联锚。
  • 我希望访问这些资源不会侵犯任何版权,因为我主要在办公室需要它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-04
  • 2011-07-13
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
相关资源
最近更新 更多