foo*_*bar 8 c++ evaluation operators parentheses short-circuiting
在处理单个短路运算符时,如何对子表达式进行分组是否重要?
a && b && c && d
a && (b && (c && d))
(a && b) && (c && d)
((a && b) && c) && d
Run Code Online (Sandbox Code Playgroud)
以上表达式是否相同?
是的,这些表达式都是等效的,包括它们的短路行为.
括号改变了&&评估各个s 的顺序.但是,由于&&始终是左关联的,因此始终按从左到右的顺序评估这些术语.因此,一旦发现某个术语为假,其余部分就可以跳过.
证明三个子表达式的两个简化情况的等价性相对容易:
a && (b && c) --> a && bc // bc is a shorthand for b && c
Run Code Online (Sandbox Code Playgroud)
在这里,a将首先进行评估.如果是假的,短路将阻止评估bc.如果是,bc则将进行评估,b && c即将进行评估.如果b为false,c则不会被评估.
(a && b) && c --> ab && c // ab is a shorthand for a && b
Run Code Online (Sandbox Code Playgroud)
在这里,ab将首先进行评估.(a && b首先评估.如果a是假,短路将阻止评估b.否则,ab产量b.)如果ab为假,c则不会被评估.
现在,如果您更喜欢证据来证明,您可以查看以下C代码的汇编输出:
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();
}
Run Code Online (Sandbox Code Playgroud)
(我使用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 ...
Run Code Online (Sandbox Code Playgroud)
生成的程序集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 ...
Run Code Online (Sandbox Code Playgroud)
生成的程序集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 ...
Run Code Online (Sandbox Code Playgroud)
生成的程序集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 ...
Run Code Online (Sandbox Code Playgroud)
如您所见,除标签外,生成的汇编代码完全相同.
| 归档时间: |
|
| 查看次数: |
698 次 |
| 最近记录: |