A recurring pattern in a piece of inherited code is that a chain of functions is called and the chain aborted, as soon as one of the functions returns a certain value. This value shall then be used for following computation. For the sake of demonstration the breaking value is 0
. Consider the following program:
#include <stdio.h>
static int n;
static int foo(int x)
{
fprintf(stderr, "%d(%d) ", x, n++);
return x ? 0 : n;
}
static void with_if(void)
{
int rc;
n = 0;
do {
if( (rc = foo(1)) ) break;
if( (rc = foo(2)) ) break;
if( (rc = foo(3)) ) break;
if( (rc = foo(4)) ) break;
if( (rc = foo(0)) ) break;
if( (rc = foo(5)) ) break;
} while(0);
fprintf(stderr, ">>%d<<\n", rc);
}
void with_short_circuit(void)
{
int rc;
n = 0;
(rc = foo(1))
|| (rc = foo(2))
|| (rc = foo(3))
|| (rc = foo(4))
|| (rc = foo(0))
|| (rc = foo(5));
fprintf(stderr, ">>%d<<\n", rc);
}
int main(int argc, char *argv[])
{
with_if();
with_short_circuit();
return 0;
}
Note that the short circuited variant is not only more concise, it's (IMHO) also far easier to read and reason about, since you don't have to push all the other surrounding statements into your mental stack, when reading that code. So I by large prefer the short circuited variant.
As far as GCC-4.9.3 and Clang-3.6.2 are concerned with_if
and with_short_circuit
are identical (they produce the very same assembly output).
What I'm worried about is, that the outcome of the boolean operator chain is ignored (if compiled with -Wall
GCC emits a warning about it, Clang remains silent though) and that this might be seen as a chance for optimization. Of course calling foo causes a side effect, hence in my understanding of the C language standard is should be safe to use boolean short circuit for control flow like this. Bit I'm not quite sure about it.