C Mastery / Operators: Assignment, Compound Assignment, Increment/Decrement
Part 1 — The Core Language

Operators: Assignment, Compound Assignment, Increment/Decrement

This chapter covers the assignment operator, the compound assignment operators, and the increment/decrement operators — including the pre/post distinction and the undefined behavior that arises when they are unsequenced.

Why This Matters

Assignment and increment/decrement are the workhorses of imperative C. Their value semantics and their sequencing rules are the source of some of the most frequently asked (and most frequently wrong) questions about C.

Prerequisites

Core Concept

Assignment

The assignment operator = stores a value in an object. Its left operand must be a modifiable lvalue. The value of the assignment expression is the value stored, after conversion to the type of the left operand.

x = 5;        /* value of the expression is 5 */
y = x = 5;    /* right-associative: both x and y become 5 */

Assignment is right-associative, so a = b = c is a = (b = c).

Compound assignment

Compound assignment combines an operation with assignment:

x += 5;    /* x = x + 5 */
x -= 5;    /* x = x - 5 */
x *= 2;    /* x = x * 2 */
x /= 2;    /* x = x / 2 */
x %= 3;    /* x = x % 3 */
x <<= 1;   /* x = x << 1 */
x >>= 1;   /* x = x >> 1 */
x &= 0x0F; /* x = x & 0x0F */
x |= 0x0F; /* x = x | 0x0F */
x ^= 0x0F; /* x = x ^ 0x0F */

For x op= y, the left operand is evaluated once, whereas x = x op y evaluates x twice. This matters when the left operand has side effects (e.g., arr[i++] += 1).

Increment and decrement

x++;   /* post-increment: value is old x, then x becomes old x + 1 */
++x;   /* pre-increment: x becomes x + 1, value is new x */
x--;   /* post-decrement */
--x;   /* pre-decrement */

The operand must be a modifiable lvalue of scalar type.

Syntax

lvalue = expression;
lvalue op= expression;
++lvalue;  --lvalue;
lvalue++;  lvalue--;

Examples

Assignment value

#include <stdio.h>

int main(void)
{
    int a, b, c;
    a = b = c = 0;   /* all become 0; assignment is right-associative */
    printf("%d %d %d\n", a, b, c);
    return 0;
}

Expected output: 0 0 0.

Compound assignment evaluates the left operand once

#include <stdio.h>

int main(void)
{
    int arr[3] = {0, 0, 0};
    int i = 0;
    arr[i++] += 1;   /* increments arr[0], then i becomes 1 */
    printf("%d %d %d\n", arr[0], arr[1], i);
    return 0;
}

Expected output: 1 0 1.

Pre vs. post

#include <stdio.h>

int main(void)
{
    int x = 5;
    int a = x++;   /* a = 5, x = 6 */
    int b = ++x;   /* x = 7, b = 7 */
    printf("%d %d %d\n", a, b, x);
    return 0;
}

Expected output: 5 7 7.

How It Works

Assignment stores a value; the stored value (converted to the left type) is the result. Compound assignment performs the operation and the assignment as a single operation. Increment/decrement add or subtract 1.

The exact *timing* of the side effect relative to other evaluations is governed by sequencing rules (c.ops.sequencing).

Variations

Assignment conversions

The right operand is converted to the type of the left operand. This can truncate or change signedness (c.types.uac).

++/-- on pointers

Pointer increment/decrement advances by the size of the pointed-to type, not by one byte (c.ptr.arithmetic).

Common Mistakes

classic bug.

for i, but the compound form evaluates i++ once.

read of i).

Undefined Behavior

i = i++, i++ + i++, and a[i] = i++ are all UB. VERIFIED

valid array object is UB (c.ptr.arithmetic).

Portability

signed overflow.

Under the Hood

x += 1 typically compiles to a single increment instruction; x = x + 1 may too, after optimization. The compiler tracks lvalues to know which memory (or register) to write.

Practical Usage

convention (modern compilers optimize both identically for scalars).

Exercises

1. Demonstrate the value of an assignment expression by chaining assignments and printing the results. 2. Show the difference between a[i++] += 1 and a[i] += 1; i++; using an array and a loop. 3. Compile int i = 0; i = i++; with warnings and UBSan enabled; explain the diagnostic.

Deep Challenge

Explain, using the standard's sequencing rules, exactly why i = i++ is undefined behavior, and give a corrected version that produces a well-defined result for every possible input.

References

§6.5.2.4 (postfix increment/decrement), §6.5.3.1 (prefix increment/ decrement).

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.ops.assign05
c.ops.incdec05