Categories
c programming tips and tricks

Short circuit operators

C’s logical operators, && (“and”) and || (“or”), let you chain together conditions when you want to take some action only when all of a set of conditions are true (&&) or when any one set of conditions is true (||). But C also provides the & and | operators. And it is vital that you understand the difference in how these work. In brief, the double-character operators (&& and ||) are called “short-circuit” operators. When used between two expressions, the second expression is only evaluated when the first expression is found to be true; otherwise it is skipped. Let’s look at an example to clarify this:

FILE *f = 0;

int short_circuit_ok() {
      int t;

      t = (int)f && feof(f);
      return t;
}

The test (int)f && feof(f) is intended to return a true value when the end of the file f is reached. This test evaluates f first; and this will be zero (a false value) if the file has not been opened. This is an error, so trying to read to the end of the file is not possible. However, since the first part of the test fails, the second part will not be evaluated, so no attempt is made on feof() . This shows the correct use of a short circuit operator to test if a file had been opened before an operation on the file is tried. But, see this code:

int short_circuit_bad() {
      int t;
      t = (int)f & feof(f);
      return t;
}

Here, the test uses the & operator instead of &&. The & operator is an instruction to evaluate both expressions in all circumstances. So, even if the first part of the test fails (as the file hasn’t been opened), the second part will be evaluated (to test for the end of the file). This could be disastrous and might cause a segmentation fault (or similar) because there is no control over the order of evaluation.

In fact, the way in which these expressions are evaluated is, to some extent, dependent on the compiler and optimizer. So, it is possible that some compilers might be smart enough to realize that this code can never succeed and therefore might not evaluate both parts of the test. Many compilers are not this smart, however; so a test of this sort in a C program, where the evaluation of one part is dependent on the other to be true, is a very bad idea!

Leave a Reply

Your email address will not be published. Required fields are marked *