We have used a few relational operators, such as < or
>, in our examples so far. These are members of a set of
relational operators that can be used in C programs which are summarised in
table 2.2
The use of the ! character to indicate the negation of a
relation is general in C, but it is important to note that ! is a
unary operator (operates on a single entity) in all cases. In some
circumstances, the arithmetic minus sign, -, acts as a unary operator, as
in the expression exp(-1.3), but the interpretation of - depends on the
context. In the expression exp(x - y), it is clear that the - acts as a
binary operator (note that there is no unary + in C). The case of
the binary operator != uses this sense of negation, but
specific to the test for inequality. Thus it would not be correct to use a
binary operator in the form !> to mean not greater than,
but of course, the <= operator does mean not greater
than. It is important to note that the equal to relational operator
is the 2-character string ``=='' and not the single character ``=''. The single
``='' character will always mean value assignment in C. Thus the result
of the statements:
x = 5;
k = x;
is to give both x and k the value 5, while the result of
the statements: x = 5;
k = (x == 3);
is to give x the value 5 and k the value 0, since the
relational test x == 3 is false (x is 5, not 3). Since an
expression like x == 3 returns a value based on the result of the test,
this value could be assigned to k in this example. Thus the result of
the statement k = (x < 10) would be to set k to one, while
k = (x >= 7) would assign k the value zero.
It is often useful to use multiple conditional tests to reach a branching decision. This is facilitated by the availability of the logical operators listed in decreasing order of precedence in table 2.3
&&'' and
``||'' are quite distinct from the 1-character strings
``&'' and ``|''. The 1-character strings represent
bit-wise operations, and are not used that frequently in the kind of
computing applications considered here.
The following sequence of C statements uses compound tests to handle the conditions under which the square root of y/x can be computed and returns -1 when it cannot be computed with real numbers.
if( ( y >= 0 && x > 0 ) || ( y <= 0 && x < 0 ) ) {
root = sqrt(y/x);
}
else {
root = -1;
}
It is important to note the fact that the precedence of each of the
arithmetic operators, <, >, <=
and >=, in this compound test statement is higher than the
&& operator, so the arithmetic tests are performed
before the && operation in each case. Since the
|| operator has a higher precedence that the
&& operators, the inner level of parentheses is actually
redundant to the C compiler. In this case they make the intention more apparent,
and have no negative implications. In fact the pair ( and ) form an operator, as
does the [ and ] pair for array element reference, with the highest precedence.
To this point, the order of evaluation of components in a C expression has been discussed in terms of operator precedence. Thus the statement
f = x / y + (x + y) * z;would result in the division being evaluated, followed by the sum x + y and the product of this with z, then the final addition, followed by the assignment of the resulting value to the variable f. In this example the order of evaluation was determined completely from the consideration of the precedence of the operators involved.
A complication arises when an expression contains a sequence of operations
where the operators have equal precedence, so that the evaluation order cannot
be determined simply from precedence. In such situations the ``tie'' is brokent
by the associativity property of each operator. A common example involves
the * and / operators in a C expression like
a * b / cSince both operators have the same precedence, the fact that both operators have left-to-right associativity must be used to determine the unique order of evaluation. In this expression the multiplication will be performed first, followed by the division. Thus the associativity properties show that the expression is equivalent to the expression
(a * b) / cwhere the parentheses enforce the order of evaluation. The result is quite different from the result of calculating
a * (b / c)where the division is done first, due to the very high precedence of the
() pair.Properties of the C operators of primary interest for our purposes are summarized in table 2.4 grouped in order of decreasing precedence, with their associativity properties. while this table only shows nine levels of precedence, it does not include bitwise C operators, since these are primarily of interest for systems programmers, rather than scientific programmers.
| Operators | Binary or Unary | Associativity |
() [] |
Unary | left to right |
- ! & * ++ -- sizeof |
Unary | right to left |
* / % |
Binary | left to right |
+ - |
Binary | left to right |
> >= < <= |
Binary | left to right |
== != |
Binary | left to right |
&& |
Binary | left to right |
|| |
Binary | left to right |
= += -= *= /= %= |
Binary | right to left |
While it is best to know in detail the precedence level of all the operators, when there is any doubt, it is best to use parentheses to force the interpretation that you, the programmer intends. Not only does this ensure that you get what you want, but it also makes it easier for another programmer to read and understand the C programs you produce.
Cengiz Şeker
2000-12-15