At its most fundamental level, the execution of a C++ program is the successive evaluation of expressions, under the control of statements (Chapter 4), in which some expressions can produce side effects. Any expression might have one or more of the following side effects:
Accessing a volatile object
Modifying an object
Calling a function in the standard library
Calling any other function that has side effects
During the execution of a program, there are well-defined points
in time called sequence points, at which the side effects
have all been completed for expressions that have been evaluated, and
no side effects have been started for any unevaluated expression.
Between sequence points, the compiler is free to reorder expressions
in any way that preserves the original semantics. The same term also
refers to the positions in the source code that produce sequence
points when the code executes. You can usually ignore the details of
sequence points, but when you are using global or
objects, it is important that you know exactly when it
is safe to access those objects. That time is after a sequence point.
Also, any expression that modifies a scalar object more than once
between sequence points, or that examines a scalar object’s value
after modifying it, yields undefined behavior. This rule often bites
the unwary programmer who uses the increment and decrement operators.
int i = 0; i = ++i - ++i; // Error: undefined behavior printf("%d,%d", ...