3.1. The Task ahead

In this chapter we look at the various ways that the control of flow statements can be used in a C program, including some statements that haven't been introduced so far. They are almost always used in conjunction with logical expressions to select the next action. Examples of logical expressions that have been seen already are some simple ones used in if or while statements. As you might have expected, you can use expressions more complicated than simple comparison (>, <=, == etc.); what may surprise you is the type of the result.

3.1.1. Logical expressions and Relational Operators

All of the examples we have used so far have deliberately avoided using complicated logical expressions in the control of flow statements. We have seen expressions like this

if(a != 100){...

and presumably you have formed the idea that C supports the concept of ‘true’ and ‘false’ for these relationships. In a way, it does, but in a way that differs from what is often expected.

All of the relational operators shown in Table 3.1 are used to compare two operands in the way indicated. When the operands are arithmetic types, the usual arithmetic conversions are applied to them.

Operator Operation
< less than
<= less than or equal to
> greater than
>= greater than or equal to
== equal to
!= not equal to
Table 3.1. Relational operators

Be extra careful of the test for equality, ==. As we have already pointed out, it is often valid to use assignment = where you might have meant == and C can't tell you about your mistake. The results are normally different and it takes a long time for beginners to get used to using == and =.

Now, that usefully introduces the question ‘why?’. Why are both valid? The answer is simple. C's concept of ‘true’ and ‘false’ boils down to simply ‘non-zero’ and ‘zero’, respectively. Where we have seen expressions involving relational operators used to control do and if statements, we have just been using expressions with numeric results. If the expression evaluates to non-zero, then the result is effectively true. If the reverse is the case, then of course the result is false. Anywhere that the relational operators appear, so may any other expression.

The relational operators work by comparing their operands and giving zero for false and (remember this) one for true. The result is of type int. This example shows how they work.

#include <stdio.h>
#include <stdlib.h>

main(){
    int i;

    i = -10;
    while(i <= 5){
            printf("value of i is %d, ", i);
            printf("i == 0 = %d, ", i==0 );
            printf("i > -5 = %d\n", i > -5);
            i++;
    }
    exit(EXIT_SUCCESS);
}
Example 3.1

Which produces this on its standard output:

value of i is -10, i == 0 = 0, i > -5 = 0
value of i is -9, i == 0 = 0, i > -5 = 0
value of i is -8, i == 0 = 0, i > -5 = 0
value of i is -7, i == 0 = 0, i > -5 = 0
value of i is -6, i == 0 = 0, i > -5 = 0
value of i is -5, i == 0 = 0, i > -5 = 0
value of i is -4, i == 0 = 0, i > -5 = 1
value of i is -3, i == 0 = 0, i > -5 = 1
value of i is -2, i == 0 = 0, i > -5 = 1
value of i is -1, i == 0 = 0, i > -5 = 1
value of i is 0, i == 0 = 1, i > -5 = 1
value of i is 1, i == 0 = 0, i > -5 = 1
value of i is 2, i == 0 = 0, i > -5 = 1
value of i is 3, i == 0 = 0, i > -5 = 1
value of i is 4, i == 0 = 0, i > -5 = 1
value of i is 5, i == 0 = 0, i > -5 = 1

In this probably mistaken piece of code, what do you think happens?

if(a = b)...

The value of b is assigned to a. As you know, the result has the type of a and whatever value was assigned to a. The if will execute the next statement if the value assigned is not zero. If zero is assigned, the next statement is ignored. So now you understand what happens if you confuse the assignment with the equality operator!

In all of the statements that test the value of an expression, the if, while, do, and for statements, the expression is simply tested to see if its value is zero or not.

We will look at each one in turn.