C CLP study materials
C CLP study resources

C CLP: Operators, Expressions, and Evaluation Order

C CLP · Work through your exam, one topic at a time.

All guide sections

Operators, Expressions, and Evaluation Order

This domain asks you to parse an expression the way the compiler does - precedence, associativity, operand grouping - and then decide whether the result is well-defined, unspecified, or undefined.

Precedence and associativity

  • Tightest: postfix () [] . ->; then unary ++ -- + - ! ~ * & sizeof (right-associative); then casts; then * / %; then + -; then shifts << >>; then relational < <= > >=; then == !=; then &, ^, |; then &&, ||; then ?: (right-associative); then assignment and compound assignment (right-associative); then the comma operator, which is lowest.
  • Shifts bind tighter than relationals, so x << 1 < y means (x << 1) < y.
  • Maximal munch: x+++y lexes as x++ + y.

Sequencing rules

  • &&, ||, ?:, and the comma operator sequence their left operand before their right one.
  • A full expression (expression statement, initializer, if/while condition, return value) is sequenced before the next statement.
  • Function-call arguments are unsequenced relative to one another; the left and right operands of + are unsequenced relative to each other.
  • Modifying an object twice, or modifying and reading it, without an intervening sequence point is undefined behaviour.

Worked example

int a = 1, b = 2, c = 3;
int x = a < b ? b, c : a;

The middle operand of ?: is parsed as if parenthesized, so this is a < b ? (b, c) : a. The comma expression evaluates b, discards it, and yields c, so x == 3. Compare x = a < b ? b : a, c;, which groups as (x = (a<b ? b : a)), c because assignment binds tighter than the comma - x gets 2 and c is evaluated and discarded.

Traps

  • if (x = 1) assigns; the missing second = is the classic defect.
  • a & b == 0 means a & (b == 0); ! binds tighter than &&.
  • Shifting by a negative count or by a count at least the type's width is undefined; right-shifting a negative value is implementation-defined.
  • A signed left shift that overflows is undefined, as is signed addition overflow.
  • i = i++ + 1 and printf("%d %d", i++, i++) are undefined, not "left to right" or "right to left".