Technical Training
C TutorialsTable of Contents
C Programming - Expressions
C Expressions - Evaluation
C Expressions - Type ConversionsC Programming - Expressions
Expressions in C are basically operators acting on operands. Statements like a = b + 3, ++z and 300 > (8 * k) are all expressions. Strictly speaking, even a single variable or constant can be considered an expression. You have seen several expressions in the previous C tutorial on Operators in which the examples involved expressions.
Precedence and Associativity
When an expression can be interpreted in more than one way, there are rules that govern how the expression gets interpreted by the compiler. Such expressions follow C's precedence and associativity rules. The precedence of operators determine a rank for the operators. The higher an operator's precedence, the higher “binding” it has on the operands.
For example, the expression a * b + c can be interpreted as (a * b) + c or a * (b + c), but the first interpretation is the one that is used because the multiplication operator has higher precedence than addition.
Associativity determines the grouping of operations among operators of the same precedence. In the expression a * b / c, since multiplication and division have the same precedence we must use the associativity to determine the grouping. These operators are left associative which means they are grouped left to right as if the expression was (a * b) / c.
The operators' order of precedence from highest to lowest and their associativity is shown in this table:
Identifier, constant or string literal, parenthesized expression
|
[] func( arglist ) . -> ++ -- |
Left associative |
|
++ -- & * + - ~ ! sizeof |
Right associative |
|
(type-name) |
Right associative |
|
* / % |
Left associative |
|
+ - |
Left associative |
|
<< >> |
Left associative |
|
< <= > >= |
Left associative |
|
== != |
Left associative |
|
& |
Left associative |
|
^ |
Left associative |
|
| |
Left associative |
|
&& |
Left associative |
|
|| |
Left associative |
|
?: |
Right associative |
|
= *= /= %= += -= <<= >>= &= ^= |= |
Right associative |
|
, |
Left associative |
The ++ and – on the second row of the table are the postfix increment and decrement operators. The func(arglist) on the second row is a function call. Functions will be covered in detail in another tutorial.
The ++ and – on the third row are the prefix increment and decrement operators. The single + and – on the third row are unary operators used to indicate a positive value or negate a value such as +3 or -a. The & on the third row is the address-of operator; the & on the 10th row is the bitwise AND operator. The (type-name) on the fourth row is an explicit cast which will be covered later in this tutorial.
Example
- int a = 9;
- int b = 4;
- int c = 6;
- printf( “%dn”, a + b * c );
The output will be 33 because the b * c multiplication has higher precedence.
The next example demonstrates the usage assignment and relational operators. Say func() is a function that returns some value. You want to assign the returned value to a variable and perform some action if the value is 3:
- int a;
- if ( a = func() == 3 )
- {
- /* do something */
- }
- /* do something with a */
However this will not work because the == has higher precedence than =, so the expression in the if statement is parsed as if (a = (func() == 3)). Therefore a is not assigned to the return value of func(), it will be set to 1 if func() returns 3, or 0 if func() does not return 3. The correct way is to use a parenthesized expression:
if (( a = func()) == 3)This example shows associativity:
int a = 3 + 4 – 2 + 7;
This works as you would expect. The expression is parsed as ((3 + 4) – 2) + 7 and 12 is assigned to a. Here is another dealing with associativity:
- #include <stdio.h>
- void main()
- {
- int a = 0;
- int b = !++*&a;
- printf( "a = %d, b = %dn", a, b );
- }
a = 1, b = 0
All the operators on line 6 ( logical not, prefix increment, dereference and address-of) all have the same precedence but they are right associative. So the right operand of the = on line 6 can be written like this: ! ( ++ ( * (&a))).
This takes the address of a, then de-references it to get a again, increments it which stores 1 in a and returns 1, then takes the logical not of 1 which is 0 and assigns that to b.
These examples show that you must pay attention to operator precedence and associativity when writing expressions. Most expressions will work as expected but there are few that can surprise you.
Pay attention to the relational operators which have higher precedence than bitwise, logical and assignment operators. If you are not sure about how an expression will be interpreted then either breaks up the expression into several expressions over multiple statements or fully parenthesize the expression.
Here is a simple example of how to break up or parenthesize an expression. Suppose the original code is like this:
- int a;
- int c;
- /* calculate a and c */
- if ( a & 0x01 == c >> 2 )
- {
- /* do something */
- }
This will be interpreted as if (a & (0x01 == (c >> 2))) which is probably not what you wanted. You could use temporary variables like this:
- int expr1 = a & 0x01;
- int expr2 = c >> 2;
- if ( expr1 == expr2 )
- {
- /* do something */
- }
The other way is to add parentheses:
- if ((a & 0x01) == (c >> 2))
- {
- /* do something */
- }
C Tutorials
- C Programming - An Overview
- C Programming - Data Types : Part 1
- C Programming - Data Types : Part 2
- C Programming - Constants and Identifiers
- C Programming - Operators
- C Programming - Expressions
- C Programming - Managing Input and Output Operations
- C Programming - Decision Making - Branching
- C Programming - Decision Making - Looping
- C Programming - Arrays
- C Programming - Handling of Character String
- C Programming - Functions (Part-I)
- C Programming - Functions (Part-II)
- C Programming - Structures and Unions
- C Programming - Pointers
- C Programming - Dynamic Memory allocation
- C Programming - Linked Lists
- C Doubly Linked Lists
- C Circular Linked Lists
- C Programming - File management in C
- C Language - The Preprocessor
- Call by Value and Call by Reference
- Concept of Pixel in C Graphics
- TSR in C - An Introduction







