A sequence point is a definite *moment* in the execution of the
program, at which all the side effects of the previous calculations
have taken place. There are several situations in which a sequence
point (SP) is known to exist. First, there is a SP at a semicolon.
There is a SP after evaluation of all arguments of a function and
just before the call to that function. There is another SP right
after the function returns. There is another SP after each object
is initialised in a definition statement. A comma operator also
introduces a SP, and so does every logical OR and logical AND
operator. I think that's about it. I don't think there are other
sequence points defined.
In 'a ? b : c', between the evaluation of a and either b or c.
The concept of a sequence point is important for allowing the C++
compiler to create certain optimizations when it generates code
from a C++ program. Sequence points are a limitation on the
execution of the program, so too many of those would mean the
code cannot be optimized. Too few of them might mean the code
won't behave predictably.
It's also important to realize that the compiler can reorder
code in an expression significantly, and if any of the legal
reorderings violate the rules, you have undefined behavior. The
classical example is something like:
f( ++ i ) + g( ++ i ) ;
Undefined behavior, since the compiler can legally reorder this
to be as:
tmp1 = ++ i
tmp2 = ++ i
f( tmp1 )
g( tmp2 )
(without any sequence points other than the function calls).
In practice, I (and I suspect that I'm not alone) find it almost
impossible to be 100% sure whether there is a sequence point or
not in some of the more subtle cases. So the general rule is to
just avoid modifying the same variable more than once in an
expression, or modifying it and using it elsewhere in the
expression. About the only exceptions I'll allow are for top
level (not in any parentheses) &&, || and ?:.