Modern C (C11/C17/C23)

the sequenced-before relation

/ SEE-kwenst /

When does one part of an expression happen before another? In a single thread, you might assume code runs strictly top to bottom, but within a single expression C gives the compiler freedom to reorder and overlap sub-computations. The sequenced-before relation is the precise rule for which evaluations are ordered, which are unordered, and where the boundaries are — and it is what decides whether code like i = i++ is well-defined.

Older C used SEQUENCE POINTS: certain points (the end of a full expression at a semicolon, the comma operator, &&, ||, ?:, and a function call's argument evaluation before the call) at which all prior side effects must be complete. C11 reframed this with three relations between evaluations A and B: sequenced-before means A is fully ordered before B; if neither is sequenced before the other they are UNSEQUENCED (the implementation may do them in any order or interleave them); and INDETERMINATELY SEQUENCED means one happens entirely before the other but you do not know which (this is how separate function calls relate). The rule that bites: if two side effects on the same object, or a side effect and a read of it, are unsequenced, the behavior is undefined.

It matters because it is the foundation of the as-if rule and of what counts as observable behavior: the compiler may reorder anything as long as the sequenced-before-visible results are preserved. The classic traps are exactly the unsequenced cases — a = a++, arr[i] = i++, or f(g(), h()) where g and h are unsequenced relative to each other — none of which you should write.

int i = 1; i = i++; // UNDEFINED: two unsequenced side effects on i int a[3], j = 0; a[j] = j++; // UNDEFINED: write a[j] and update j are unsequenced // well-defined instead: i++; or a[j] = 0; j++;

Two unsequenced modifications of i (or a write and an update of j) are undefined behavior, not merely 'unpredictable'.

Unsequenced side effects on the same object are undefined behavior — the compiler may assume it never happens and optimize accordingly, so the result is not just 'some order', it has no defined meaning at all.

Also called
sequencingsequence points (older model)定序序列點