Hierarchy of Operations in C
While executing an arithmetic statement, which has two or more operators, we may have some problems as to how exactly does it get executed.
For example, does the expression 2 * x – 3 * y correspond to (2x)-(3y) or to 2(x-3y)?
Similarly, does A / B * C correspond to A / (B * C) or to (A / B) * C? To answer these questions satisfactorily one has to understand the ‘hierarchy’ of operations. The priority or precedence in which the operations in an arithmetic statement are performed is called the hierarchy of operations.
Now a few tips about usage of operators in general.
- Within parentheses the same hierarchy as mentioned above is operative. Also, if there are more than one set of parentheses, the operations within the innermost parentheses would be performed first, followed by the operations within the second innermost pair and so on.
- We must always remember to use pairs of parentheses. A careless imbalance of the right and left parentheses is a common error. Best way to avoid this error is to type ( ) and then type an expression inside it.
Example:
Determine the hierarchy of operations and evaluate the following expression:
i = 2 * 3 / 4 + 4 / 4 + 8 – 2 + 5 / 8
Step wise evaluation of this expression is shown below:
i = 2 * 3 / 4 + 4 / 4 + 8 – 2 + 5 / 8
i = 6 / 4 + 4 / 4 + 8 – 2 + 5 / 8 operation: *
i = 1 + 4 / 4 + 8 – 2 + 5 / 8 operation: /
i = 1 + 1+ 8 – 2 + 5 / 8 operation: /
i = 1 + 1 + 8 – 2 + 0 operation: /
i = 2 + 8 – 2 + 0 operation: +
i = 10 – 2 + 0 operation: +
i = 8 + 0 operation : –
i = 8 operation: +
Explanation:
Note that 6 / 4 gives 1 and not 1.5. This so happens because 6 and 4 both are integers and therefore would evaluate to only an integer constant. Similarly 5 / 8 evaluates to zero, since 5 and 8 are integer constants and hence must return an integer value.
Example 2:
Determine the hierarchy of operations and evaluate the following expression:
kk = 3 / 2 * 4 + 3 / 8 + 3
Stepwise evaluation of this expression is shown below:
kk = 3 / 2 * 4 + 3 / 8 + 3
kk = 1 * 4 + 3 / 8 + 3 operation: /
kk = 4 + 3 / 8 + 3 operation: *
kk = 4 + 0 + 3 operation: /
kk = 4 + 3 operation: +
kk = 7 operation: +
Explanation:
Note that 3 / 8 gives zero, again for the same reason mentioned in the previous example.
All operators in C are ranked according to their precedence. And mind you there are as many as 45 odd operators in C, and these can affect the evaluation of an expression in subtle and unexpected ways if we aren’t careful. Unfortunately, there are no simple rules that one can follow, such as “BODMAS” that tells algebra students in which order does an expression evaluate. We have not encountered many out of these 45 operators, so we won’t pursue the subject of precedence any further here. However, it can be
realized at this stage that it would be almost impossible to remember the precedence of all these operators.
This may sound daunting, but when its contents are absorbed in small bites, it becomes more palatable.
So far we have seen how the computer evaluates an arithmetic statement written in C. But our knowledge would be incomplete unless we know how to convert a general arithmetic statement to a C statement. C can handle any complex expression with ease. Some of the examples of C expressions are shown below.
Associativity of Operators
When an expression contains two operators of equal priority the tie between them is settled using the associativity of the operators. Associativity can be of two types—Left to Right or Right to Left. Left to Right associativity means that the left operand must be unambiguous. Unambiguous in what sense? It must not be involved in evaluation of any other sub-expression. Similarly, in case of Right to Left associativity the right operand must be unambiguous. Let us understand this with an example.
Consider the below expression
a = 3 / 2 * 5 ;
Here there is a tie between operators of same priority, that is between / and *. This tie is settled using the associativity of / and *. But both enjoy Left to Right associativity.
Let see below which operand is unambiguous and which is not.
Since both / and * have L to R associativity and only / has unambiguous left operand (necessary condition for L to R associativity) it is performed earlier. Consider one more expression
a = b = 3 ;
Here both assignment operators have the same priority and same associativity (Right to Left).
Since both = have R to L associativity and only the second = has unambiguous right operand (necessary condition for R to L associativity) the second = is performed earlier.Consider yet another expression
z = a * b + c / d ;
Here * and / enjoys same priority and same associativity (Left to Right).
Here since left operands for both operators are unambiguous Compiler is free to perform * or / operation as per its convenience since no matter which is performed earlier the result would be
same.