Does it matter how I group subexpressions when dealing with a single short-circuiting operator?
a && b && c && d
a && (b && (c && d))
(a && b) && (c && d)
((a && b) && c) && d
Are the above expressions equivalent?
It is relatively easy to prove the equivalence for two simplified cases of three subexpressions:
a && (b && c) --> a && bc // bc is a shorthand for b && c
Here, a
will be evaluated first. If it is false, short circuiting will prevent the evaluation of bc
. If it is true, bc
will be evaluated, that is, b && c
will be evaluated. If b
is false, c
won't be evaluated.
(a && b) && c --> ab && c // ab is a shorthand for a && b
Here, ab
will be evaluated first. (That is a && b
is evaluated first. If a
is false, short circuiting will prevent the evaluation of b
. Otherwise, ab
yields b
.) If ab
is false, c
won't be evaluated.
Now, if you prefer evidence to proof, you can look at the assembly output of the following C code:
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();
}
(I used C code as opposed to C++ code to prevent name mangling.)
generated assembly for 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 ...
generated assembly for 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 ...
generated assembly for 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 ...
generated assembly for 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 ...
As you can see, apart from labels, the generated assembly code is completely identical.