"no diagnostic required"的理由是什么?

What is the rationale to "no diagnostic required"?

本文关键字:是什么 理由 required no diagnostic      更新时间:2023-10-16

大多数人都熟悉c++中的"undefined"answers"unspecified"行为注释,那么"no diagnostic required"呢?

我注意到这个问题和答案,处理格式不良的程序,但没有详细说明"不需要诊断"语句的根源。

委员会在将某物分类为"不需要诊断"时采用的一般方法是什么?

  • 标准委员会需要多严重的错误来指定它?
  • 这些错误的性质是否几乎不可能检测到,因此无法诊断?

"未定义"answers"未指定"行为的例子比比皆是;除了ODR之外,还有哪些"不需要诊断"类型错误的实际示例?

这里有一个讨论:https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/lk1qavcivility与各委员会成员的话语。

普遍的共识似乎是

  • 无规范性差异
  • 不规范的;仅用于编译时规则违规,从不用于运行时规则违规。

正如我在那篇文章中所说的,我确实在一次讨论中听到过(我记不清是哪一次了,但我肯定有有见地的委员会成员参与其中)

  • 不规范的;对于明显违反规则的情况,不需要诊断,原则上可以在编译时诊断,但需要实现付出巨大的努力。
  • 未定义的行为用于实现可以找到有用意义的事情,因此不一定是纯粹的邪恶,以及任何导致任意后果的运行时违规。

我的粗略指南是;如果它是在编译时,它往往是"病态的;如果是在运行时,它总是"未定义行为"。

对于归类为未定义行为(UB)的行为,我会尝试解释"无需诊断"

标准说"UB不需要诊断"1,给编译器完全的自由来优化代码,因为编译器只能通过假设你的程序是完全定义良好的(这意味着你的程序没有UBs)来消除许多开销,这是一个好的假设—毕竟,如果这个假设是错误的,那么编译器基于这个(错误的)假设所做的任何事情都将以一种未定义的(即不可预测的)方式表现,这是完全一致的,因为你的程序无论如何都有未定义的行为!

请注意,包含UBs的程序具有像任何东西一样的行为自由。再次注意,我说"一致"是因为它与标准的立场是一致的:"语言规范和编译器都不能保证你的程序的行为,如果它包含UB"

<一口> 1。与之相反的是"诊断要求",这意味着编译器被要求通过发出警告错误消息向程序员提供诊断。换句话说,不允许假定程序定义良好,从而优化代码的某些部分。

这里有一篇文章(在LLVM博客上)用例子进一步解释了这一点:

  • C语言中未定义行为的优点,附示例(第一部分)

文章的例外(斜体mine):

有符号整型溢出:如果对'int'类型进行算术处理(例如)溢出,结果未定义。例如,"INT_MAX+1"是不能保证是INT_MIN。的某些类对某些代码来说很重要的优化。例如,知道INT_MAX+1未定义允许将"X+1> X"优化为"true"。知道乘法"不能"溢出(因为这样做会未定义)允许将"X*2/2"优化为"X"。虽然这些看起来微不足道,这类事情通常通过内联和宏扩展。这允许的更重要的优化是"<="像这样循环:

for (i = 0; i <= N; ++i) { ... }

在此循环中,编译器可以假定循环将进行迭代如果"i"在溢出时未定义,则恰好是N+1倍,这允许a广泛的循环优化启动。另一方面,如果变量被定义为在溢出时绕行,然后是编译器必须假设循环可能是无限的(如果N是INT_MAX)——然后禁用这些重要的循环优化。这尤其会影响64位平台,因为有太多的代码使用"int"作为归纳变量

值得注意的是,保证定义了无符号溢出因为2的补码(换行)溢出,所以你总是可以使用它们。的定义有符号整数溢出的代价是优化只是失去了(例如,一个常见的症状是吨在64位目标上的循环内的符号扩展)。Clang和GCC接受"-fwrapv"标志,该标志强制编译器处理定义的有符号整数溢出(除了INT_MIN除以1) .

我建议你阅读整篇文章—它有三个部分,都很好。

  • 第二部分
  • 第三部分

希望对你有帮助。