Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 永远不会执行的代码能否调用未定义的行为?_C_Language Lawyer - Fatal编程技术网

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).