Operator Precedence
Operator Precedence Table
C has a a lot of implied behavior, operator chaining, and undefined behavior traps. Hence the importance of operator precedence.
Empty cells copy the same contents as the one above it.
| Precedence | Operator | Description | Associativity |
|---|---|---|---|
| 1 | () |
Parentheses (function call) | Left-to-Right |
[] |
Array access | ||
. |
For structs (access fields) |
||
-> |
struct . and dereference (*) |
||
++, -- |
Postfix increment and decrement | ||
| 2 | ++, -- |
Prefix increment, decrement | Right-to-Left |
+, - |
Unary plus/minus, related to the signs of numbers (pos/neg) | ||
!, ~ |
Logical NOT, Bitwise complement | ||
(type) |
Type casting | ||
* |
Dereference operator | ||
& |
Get memory address | ||
sizeof |
Get the size of something in bytes | ||
| 3 | *, /, % |
Multiplication, division, modulus | Left-to-Right |
| 4 | +, - |
Addition, subtraction | Left-to-Right |
| 5 | <<, >> |
Bitwise shift left, Bitwise shift right | Left-to-Right |
| 6 | <, <= |
Less than, less than or equal to | Left-to-Right |
>, >= |
Greater than, greater than or equal to | ||
| 7 | ==, != |
Is equal to, is not equal to | Left-to-Right |
| 8 | & |
Bitwise AND | Left-to-Right |
| 9 | ^ |
Bitwise XOR | Left-to-Right |
| 10 | \| |
Bitwise OR | Left-to-Right |
| 11 | && |
Logical AND | Left-to-Right |
| 12 | \|\| |
Logical OR | Left-to-Right |
| 13 | ? (expr) : (expr) |
(CONDITION) ? (expr) : (expr) (Tenary conditional) |
Right-to-Left |
| 14 | = |
Assignment | Right-to-Left |
+=, -= |
Addition, subtraction assignment | ||
*=, /= |
Multiplication, division assignment | ||
%=, &= |
Modulus, bitwise AND assignment | ||
^=, \|= |
Bitwise exclusive, inclusive OR assignment | ||
<<=, >>= |
Bitwise shift left, right assignment | ||
| 15 | , |
Comma (expression separator) | Left-to-Right |
Postfix vs Prefix
#include <stdio.h>
int main(void)
{
int i, j = 0;
printf("i: %d j: %d", i++ + 1, ++j + 1);
return 0;
}
Postfix returns the value of the variable first, then does the increment (or decrement w/ i--
or j--), and the opposite goes for prefix.
So the value of the printf for i++ + 1 would be 1, but after that, i’s value would be 1 (due to i++). And the value for ++j + 1 would be 2, but since the + 1 isn’t a += ,++, or something similar, j’s value would be 1 (again, due to ++j).
When you’re declaring a for loop: (etc)
for (int i = 0; i < n; ++i)
;
It doesn’t really matter, purely user preference.
What about expressions like these?
int a[3] = {1, 2, 3};
int i = 3;
while (i--)
{
... // code
}
int a[3] = {1, 2, 3};
int * b = a;
for (int i = 0; i < 3; ++i)
*b++ = 0; // set everything to 0
Remember that postfix ++ or -- doesn’t increment on the spot, AND it first returns the current value of the variable (the value before it pluses/minuses 1). It will increment once the expression is finished. It’s like a “I will increment soon” signal.
So the i-- on the first iteration will go through because the while loop condition is while (3), but once you go into the loop body, i is 2.
#C #C/conceptual