Operators
Arithmetic, the integer-division trap, comparison, short-circuit logical operators, bitwise AND/OR/XOR/NOT, shifts, compound assignment, precedence traps, ternary.
Ten pieces, and at least three of them are classic C traps I now actively watch for: the integer division trap, short-circuit evaluation, and precedence surprises around the bitwise operators.
Arithmetic and the integer division trap
int a = 5 / 2; // 2, not 2.5 — integer division truncates
float b = 5 / 2; // still 2.0 — the division happens before the assignment
float c = 5.0 / 2; // 2.5 — one operand being float is enoughThe result type is decided entirely by the operand types at the point of division — not by whatever it gets assigned into afterward. If both operands are int, it's integer division, full stop.
Comparison and short-circuit logic
== != < > <= >=— straightforward, but==vs=is the classic typo that compiles fine and does something completely different.&&and||short-circuit — if the left side of&&is false, the right side is never evaluated at all, including any side effects it would have had. Same for||when the left side is true.
Bitwise operators
| Operator | Meaning |
|---|---|
& | AND — bit set only if both bits are set |
| | OR — bit set if either bit is set |
^ | XOR — bit set if exactly one bit is set |
~ | NOT — flips every bit |
<< | shift left — multiply by 2 per shift |
>> | shift right — divide by 2 per shift (implementation-defined on signed negatives) |
The precedence trap
if (a & b == c) // parses as a & (b == c) — almost never what I actually mean
if ((a & b) == c) // what I actually mean== binds tighter than &, so a bare a & b == c silently does the comparison first and ANDs the result against a. Bitwise expressions being compared always need explicit parentheses — I stopped trusting myself to remember the precedence table and just parenthesize by default now.
Compound assignment, increment/decrement, and the ternary
+= -= *= /= %= &= |= ^= <<= >>=— compound assignment, shorthand forx = x op y.x++(postfix) — evaluates to the old value, then increments.++x(prefix) — increments first, then evaluates to the new value.cond ? a : b— a single expression, not a statement. It has to produce a value, both branches have to be the same type, and it can't stand in for anifwith noelse.
Notes from readers
Comments — via GitHub