在处理单个短路运算符时,我如何分组子表达式是否重要?
a && b && c && d
a && (b && (c && d))
(a && b) && (c && d)
((a && b) && c) && d
这些表达式是等价的吗?
在处理单个短路运算符时,我如何分组子表达式是否重要?
a && b && c && d
a && (b && (c && d))
(a && b) && (c && d)
((a && b) && c) && d
是的,这些表达式都是等价的,包括它们的短路行为。
括号改变了单个&&
的求值顺序。然而,由于&&
总是从左往右结合,因此术语总是按照从左到右的顺序进行评估。因此,一旦发现一个术语为假,就可以跳过其余部分。
对于三个子表达式的两种简化情况,证明等价性相对容易:
a && (b && c) --> a && bc // bc is a shorthand for b && c
a
。如果它为假,短路将防止评估bc
。如果它为真,则会评估bc
,即将评估b && c
。如果b
为假,则不会评估c
。(a && b) && c --> ab && c // ab is a shorthand for a && b
int a(), b(), c(), d();
void e()
{
a() && b() && c() && d();
}
void f()
{
a() && (b() && (c() && d()));
}
void g()
{
(a() && b()) && (c() && d());
}
void h()
{
((a() && b()) && c()) && d();
}
我使用C代码而不是C++代码,以防止名称混淆。
e
的生成汇编:
_e:
// ... enter ...
call _a
testl %eax, %eax
je L1
call _b
testl %eax, %eax
je L1
call _c
testl %eax, %eax
je L1
call _d
testl %eax, %eax
nop
L1:
// ... leave ...
f
的生成汇编代码:
_f:
// ... enter ...
call _a
testl %eax, %eax
je L4
call _b
testl %eax, %eax
je L4
call _c
testl %eax, %eax
je L4
call _d
testl %eax, %eax
nop
L4:
// ... leave ...
g
的生成汇编代码:
_g:
// ... enter ...
call _a
testl %eax, %eax
je L7
call _b
testl %eax, %eax
je L7
call _c
testl %eax, %eax
je L7
call _d
testl %eax, %eax
nop
L7:
// ... leave ...
h
的汇编代码生成:
_h:
// ... enter ...
call _a
testl %eax, %eax
je L10
call _b
testl %eax, %eax
je L10
call _c
testl %eax, %eax
je L10
call _d
testl %eax, %eax
nop
L10:
// ... leave ...
正如您所看到的,除了标签之外,生成的汇编代码完全一致。
在你的例子中,括号并不重要。但这只是由于&&的性质,所有术语都需要被检查(如果为真,或者如果任何一个为假,则为假)。
在这个例子中,括号确实有很大的区别:
(a && b) || (c && d) // either a & b are true, or c & d
a && (b || c && d) // a must be true, and either b or c & d
(a && b || c) && d // d must be true, and either c or a & b
operator&&
是完全结合的,因此上述规则适用。operator-
通常是左结合的,即a - b - c == (a - b) - c != a - (b - c)
a ** b ** c == a ** (b ** c) != (a ** b) ** c
(a x b) x c != a x (b x c)
(而且没有括号时,表达式甚至没有意义)请注意,这仅适用于单个运算符被一致使用的情况,一旦引入另一个运算符(如||
),则必须考虑运算符优先级,这是另一个主题。
operator&&
是完全关联时,我就解决了。如果短路行为不能被保持,那么我们就无法将运算符定义为关联的。 - Matthieu M.&&
是左结合的。公平地说,我并不真正知道这意味着什么,因为没有其他运算符具有相同的优先级。 - Oliver Charleswortha && b && c == (a && b) && c != a && (b && c)
пјҢжҲ‘дјҡиҜҙиҝҷжҳҜй”ҷиҜҜзҡ„пјҢжҲ–иҖ…е®ғеҸҜд»Ҙж„Ҹе‘ізқҖa && b && c == (a && b) && c
пјҢеҝҳи®°еҸіе…іиҒ”гҖӮеҪ“иҜ„дј°a && (b && c)
ж—¶пјҢеҰӮжһңa
дёәfalseпјҢеҲҷеҒңжӯўпјҢеҗҰеҲҷиҜ„дј°b && c
пјҢеҰӮжһңb
дёәfalseеҲҷзҹӯи·ҜпјҢеҗҰеҲҷиҜ„дј°c
гҖӮеӣ жӯӨпјҢ&&
жҳҜе®Ңе…Ёе…іиҒ”зҡ„пјҢ并且жӮЁеҸҜд»ҘиҜҙе®ғжҳҜе·Ұе…іиҒ”зҡ„пјҲе°Ҫз®ЎдёҚдёҘж јпјүгҖӮ - Matthieu M.a && b && c == (a && b) && c
。但这并不一定意味着 != a && (b && c)
。 - Oliver Charlesworth