When a sequence point occurs, it basically means that you are guaranteed that all previous operations are complete.
Changing a variable twice without an intervening sequence point is one example of undefined behaviour.
For example, i = i++; is undefined because there’s no sequence point between the two changes to i.
Note that it’s not just changing a variable twice that can cause a problem. It’s actually a change involved with any other use. The standard uses the term “value computation and side effect” when discussing how things are sequenced. For example, in the expression
a = i + i++, thei(value computation) andi++(side effect) may be done in arbitrary order.
Wikipedia has a list of the sequence points in the C and C++ standards although the definitive list should always be taken from the ISO standard. From C11 appendix C (paraphrased):
The following are the sequence points described in the standard:
- Between the evaluations of the function designator and actual arguments in a function call and the actual call;
- Between the evaluations of the first and second operands of the operators
&&,||, and,; - Between the evaluations of the first operand of the conditional
?:operator and whichever of the second and third operands is evaluated; - The end of a full declarator;
- Between the evaluation of a full expression and the next full expression to be evaluated. The following are full expressions:
- an initializer;
- the expression in an expression statement;
- the controlling expression of a selection statement (
iforswitch); - the controlling expression of a
whileor do statement; - each of the expressions of a
forstatement; - the expression in a return statement.
- Immediately before a library function returns;
- After the actions associated with each formatted input/output function conversion specifier;
- Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call.