C 永远不会执行的代码能否调用未定义的行为?
调用未定义行为(在本例中为零除)的代码将永远不会执行,程序仍然是未定义行为吗C 永远不会执行的代码能否调用未定义的行为?,c,language-lawyer,C,Language Lawyer,调用未定义行为(在本例中为零除)的代码将永远不会执行,程序仍然是未定义行为吗 int main(void) { int i; if(0) { i = 1/0; } return 0; } 我认为这仍然是未定义的行为,但我在标准中找不到任何支持或否定我的证据 那么,有什么想法吗?在这种情况下,未定义的行为是执行代码的结果。因此,如果代码没有执行,就没有未定义的行为 如果未定义的行为仅仅是代码声明的结果,则未执行的代码可能会调用未定义的行为(
int main(void)
{
int i;
if(0)
{
i = 1/0;
}
return 0;
}
我认为这仍然是未定义的行为,但我在标准中找不到任何支持或否定我的证据
那么,有什么想法吗?在这种情况下,未定义的行为是执行代码的结果。因此,如果代码没有执行,就没有未定义的行为
如果未定义的行为仅仅是代码声明的结果,则未执行的代码可能会调用未定义的行为(例如,如果变量阴影的某些情况未定义)。我将使用此答案的最后一段: 。。。UB是运行时问题,而不是编译时问题
所以,不,没有UB被调用。标准说,正如我记得的那样,从规则被打破的那一刻起,它就可以做任何事情。也许有一些具有全球风味的特别活动(但我从未听说或读到过类似的事情)。。。所以我想说:不,这不可能是UB,因为只要行为定义正确,0总是错误的,所以规则在运行时不会被破坏。这在第2.6节讨论了这个问题:
int main(void){
guard();
5 / 0;
}
作者认为程序在<代码>句柄()> /代码>不终止时定义。他们还发现自己区分了“静态未定义”和“动态未定义”的概念,例如:
standard11背后的意图似乎是,通常情况下,如果不容易为这些情况生成代码,则这些情况是静态未定义的。只有当代码可以生成时,情况才能动态地取消定义 11) 与委员会成员的私人通信 我建议您阅读整篇文章。综上所述,它描绘了一幅始终如一的画面这篇文章的作者不得不与一位委员会成员讨论这个问题,这一事实证实了该标准目前对您的问题的答案是模糊的。只有当标准做出了突破性的更改,并且您的代码突然不再“永远不会执行”时。但我看不出这会导致“未定义行为”的任何逻辑方式。它不会导致任何问题。让我们看看C标准是如何定义术语“行为”和“未定义行为”的 参考ISO C 2011标准草案;我不知道三个已发布的ISO C标准(1990、1999和2011)中有任何相关差异 第3.4节: 行为
外表或行为 好吧,这有点模糊,但我认为给定的语句没有“外观”,当然也没有“动作”,除非它实际执行 第3.4.3节: 未定义的行为
使用不可移植或错误的程序结构或错误的数据时的行为, 本国际标准对其无任何要求 上面写着“使用”这样的结构。标准中没有定义“使用”一词,因此我们回到了普通的英语意思。如果构造从未执行过,则不会“使用” 在该定义下有一个注释: 注意:可能的未定义行为包括忽略情况 完全不可预测的结果,在翻译过程中的行为 或以文件化的方式执行程序 环境(无论是否发出诊断消息),以 终止翻译或执行(通过发布 诊断信息) 因此,如果程序的行为未定义,编译器可以在编译时拒绝您的程序。但我对此的解释是,只有当它能够证明程序的每次执行都会遇到未定义的行为时,它才能这样做。我认为这意味着:
if (rand() % 2 == 0) {
i = i / 0;
}
它当然可以有未定义的行为,不能在编译时被拒绝
实际上,程序必须能够执行运行时测试以防止调用未定义的行为,并且标准必须允许它们这样做
你的例子是:
if (0) {
i = 1/0;
}
它从不执行0的除法。一个非常常见的成语是:
int x, y;
/* set values for x and y */
if (y != 0) {
x = x / y;
}
如果y==0
,则该除法当然具有未定义的行为,但如果y==0
,则该除法永远不会执行。行为定义得很好,与示例定义得很好的原因相同:因为潜在的未定义行为永远不会发生
(除非INT\u MIN<-INT\u MAX&&x==INT\u MIN&&y=-1
(是的,整数除法可能溢出),但这是一个单独的问题。)
在一篇评论中(删除后),有人指出编译器可能在编译时计算常量表达式。这是正确的,但与本例无关,因为在
i = 1/0;
1/0
不是一个常量表达式
常量表达式是一种语法类别,它简化为条件表达式(不包括赋值和逗号表达式)。生产常量表达式仅在实际需要常量表达式的上下文(如大小写标签)中出现在语法中。所以如果你写:
switch (...) {
case 1/0:
...
}
然后,1/0
是一个常量表达式,它违反了6.6p4中的约束:“每个常量表达式的计算结果应在可表示的范围内
类型“”的值,因此需要进行诊断。但是赋值的右侧不需要常量表达式,只需要条件表达式,因此常量表达式上的约束不适用。编译器可以在编译时计算它能够计算的任何表达式,但前提是该行为与在执行期间计算的行为相同(或者,在if(0)
的上下文中,与在执行期间未计算的行为相同()
(看起来完全像常量表达式的东西是不必要的
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of
erroneous data, for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely
with unpredictable results, to behaving during translation or program execution
in a documented manner characteristic of the environment (with or without the
issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message).