未定义的行为是否未被评估?

我对以下代码与一些同事存在分歧:

int foo ( int a, int b ) { return b > 0 ? a / b : a; } 

这段代码是否performance出未定义的行为?

编辑:分歧从什么似乎是过度急切的优化编译器,其中b > 0检查被优化出来的错误。

没有。


来自N4140的引述:

§5.16[expr.cond] / 1

条件expression式从右到左分组。 第一个expression式被上下文转换为bool。 它被评估,如果它是真的,条件expression式的结果是第二个expression式的值,否则第三个expression式的值。 只有 第二个和第三个expression式中的一个被评估

进一步:

§5[expr] / 4

如果在expression式评估过程中,结果不是math定义的,或者不在其types的可表示值范围内,则行为是未定义的。

这显然不会发生在这里。 同一段在一个注释中明确提到零除,虽然它是非规范性的,但它更加清楚地表明它与这种情况有关:

[注:大多数现有的C ++实现忽略整数溢出。 除零的处理,使用零除数形成余数,并且所有浮点exception在机器之间变化,并且通常可以通过库函数进行调整。 – 注意]


还有一些间接证据强化了上述观点:条件操作符被用来有条件地使行为不被定义。

§8.5[dcl.init] /12.3

 int f(bool b) { unsigned char c; unsigned char d = c; // OK, d has an indeterminate value int e = d; // undefined behavior return b ? d : 0; // undefined behavior if b is true } 

在上面的例子中,使用d初始化int (或者unsigned char以外的任何东西)是未定义的。 但是很清楚地表明,UB只有在UB分支被评估的情况下才会发生。


从语言律师的angular度出发:如果这可能是UB,那么任何部门都可以被视为UB,因为除数可能为0.这不是规则的精神。

示例代码中无法用零来划分。 当处理器执行a / b ,它已经检查b > 0 ,因此b不为零。

应该注意的是,如果a == INT_MINb == -1 ,那么a/b也是未定义的行为。 但是无论如何这都是被阻止的,因为在这种情况下条件评估是false

虽然我不确定你的意思是return b != 0 ? a / b : a; return b != 0 ? a / b : a; 而不是return b > 0 ? a / b : a; return b > 0 ? a / b : a; 如果b小于零,除非是上述条件,否则除法仍然有效。

这段代码是否performance出未定义的行为?

不,不。 expression方式

 return b > 0 ? a / b : a; 

相当于

 if(b > 0) return a/b; // this will be executed only when b is greater than 0 else return a; 

只有当b大于0时才会执行除法。

如果这是UB,那么也是如此

 if(a != null && *a == 42) { ..... } 

ifs,ands和ors的sorting明确地被devise为专门允许这种types的构造。 我无法想象你的同事会这样争论