大多数人都熟悉" undefined"和"未指明" C ++中的行为记录,但是"不需要诊断"?
我注意this question and answer,处理不良形成的程序,但没有详细说明"根本不需要诊断"语句。
委员会在将某些内容归类为&#34时所采用的一般方法是什么?不需要诊断"?
" undefined"的例子和"未指明"行为不是短缺的;在没有ODR的情况下,有什么实际的例子可以用于"不需要诊断"输入错误?
答案 0 :(得分:12)
这里有一个讨论:https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/lk1qAvCiviY由各委员会成员发言。
普遍的共识似乎是
正如我在那个帖子中所说,我曾经在一次讨论中听过(我不记得在哪一个,但我确信有很多有见地的委员会成员参与)
对我来说粗略的指南是;如果它在编译时,它往往是“格式错误;不需要诊断”,如果它在运行时,它总是“未定义的行为”。
答案 1 :(得分:11)
我会尝试解释"不需要诊断" 分类为未定义行为(UB)的行为。
标准通过说&#34; UB不需要诊断&#34; 1 ,使编译器完全自由地优化代码,因为编译器只能通过<消除许多开销em>假设你的程序是完全明确的(这意味着你的程序没有UB),这是一个良好的假设 - 毕竟如果这个假设是错误的,那么任何东西基于这个(错误的)假设的编译器会以一种未定义的(即不可预测的)方式运行,这种方式完全一致,因为你的程序还有未定义的行为!
请注意,包含UB的程序可以像任何行为一样自由。再次注意我说&#34;一致&#34;因为它与标准的立场是一致的:&#34;如果语言规范和编译器包含UB(s)&#34;
1。 相反的是&#34;需要诊断&#34;这意味着编译器必需通过发出警告或错误消息向程序员提供诊断。换句话说,不允许假设程序定义明确,以优化代码的某些部分。
这是一篇文章(在LLVM博客上),它使用示例进一步解释了这一点:
除了文章( italicised mine )之外:
有符号整数溢出:如果对&#39; int&#39;进行算术运算类型(例如) 溢出,结果未定义。一个例子是&#34; INT_MAX + 1&#34;是 不保证是INT_MIN。 此行为启用某些类 对某些代码很重要的优化。例如,知道 INT_MAX + 1未定义允许优化&#34; X + 1&gt; X&#34; to&#34; true&#34;。 知道乘法&#34;不能&#34;溢出(因为这样做会 未定义)允许优化&#34; X * 2/2&#34;到&#34; X&#34; 。虽然看起来很像 琐碎的,这些东西通常都是通过内联和内联来暴露的 宏观扩张。这允许的更重要的优化是 &#34;&LT; =&#34;像这样的循环:
for (i = 0; i <= N; ++i) { ... }
在此循环中,编译器可以假定循环将迭代 如果&#34; i&#34;正好是N + 1次溢出时未定义,允许a 广泛的循环优化可以启动。另一方面,如果 变量被定义为在溢出时回绕,然后是编译器 必须假设循环可能是无限的(如果N是,则会发生 INT_MAX) - 然后禁用这些重要的循环优化。 由于代码使用太多,这尤其会影响64位平台 &#34; INT&#34;作为诱导变量。
值得注意的是,保证定义无符号溢出 作为2的补充(包装)溢出,所以你总是可以使用它们。该 制定有符号整数溢出的成本就是这些 简单地丢失优化(例如,常见的症状是吨 64位目标上循环内的符号扩展名)。 Clang和 海湾合作委员会接受&#34; -fwrapv&#34;标志强制编译器处理 定义的有符号整数溢出(除了INT_MIN除以之外) -1)。
我建议你阅读整篇文章 - 它有三个部分,一切都很好。
希望有所帮助。