我很好奇关于条件子句中变量赋值的C标准的确切定义。这是一个小例子:
int foo() {
...
}
int bar() {
...
}
int main () {
int a, b, x, y;
...
if ( (a = foo()) == x && (b = bar() == y ) {
...
}
...
}
GCC测试显示,如果(a = foo()) != x
,b = bar()
将不会被执行。一方面,这种行为是最佳的,因为它不会浪费任何时间计算bar()
。但另一方面,b
的值有些未定义,因为它取决于foo()
的结果,实际上与b
无关。
我想知道C标准中是否有明确的此类案例定义,以及该定义的原因是什么。最后,编写此类代码被认为是最佳实践?
答案 0 :(得分:0)
这非常简单:如果第一个参数的计算结果为0,则&&
的第二个(即右手)参数将不进行评估。
因此,如果(b = bar() == y )
为0,则(a = foo()) == x
将不进行评估。
事实上,这可能使b
未初始化 - 可能是未定义的结果 - 是一个试金石,因为你不应该用这种方式编码。
你可以使用
if ((a = foo() == x) & (b = bar() == y))
如果您希望始终评估双方:&
不会被短路。但是如果参数可以计算为0或1以外的值(在这种情况下它们不是这样),请注意意外的效果。
答案 1 :(得分:0)
GCC测试显示,如果(a = foo())!= x,则b = bar()将不会被执行。
嗯,这是逻辑AND(&&
)运算符的属性。
引用C11
,章节§6.5.13,强调我的
与按位二进制&操作员,&&运营商保证从左到右的评估; 如果计算第二个操作数,则在评估之间存在一个序列点 第一和第二个操作数。 如果第一个操作数比较等于0,则第二个操作数 操作数未被评估。
也就是说,对于b
的赋值,你是对的,如果第一个操作数是FALSE,b
的值仍然是不确定的,并且任何使用变量可能会导致undefined behavior。
(其中之一)最佳实践,是在定义时初始化局部变量,以避免使用不确定的值。
答案 2 :(得分:0)
运算符&&
由短路评估组成:第二个子表达式仅在需要其结果时才进行评估,以确定整个表达式的结果。
在您的示例中,在表达式中:
(a = foo()) == x && (b = bar() == y)
如果第一个子表达式(a = foo()) == x
被评估为false,则无论子表达式(b = bar() == y)
将产生什么结果,上面表达式的结果也都是假的。
由于短路评估和(a = foo()) == x
评估为false的事实,从不评估表达式(b = bar() == y)
。