37

A sequence point in imperative programming defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed.

What does this mean? Can somebody please explain it in simple words?

Jagan
  • 4,649
  • 19
  • 60
  • 70
  • possible duplicate of [Sequence points and partial order](http://stackoverflow.com/questions/1895922/sequence-points-and-partial-order) – jev Oct 16 '13 at 13:06

4 Answers4

61

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++, the i (value computation) and i++ (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 (if or switch);
    • the controlling expression of a while or do statement;
    • each of the expressions of a for statement;
    • 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.
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 3
    It is also undefined behavior to modify the value of a variable and also use the value in any way other than to determine the value to be stored without an intervening sequence point. For example, a[i++] = i is undefined because, although it only modifies the value of i once, the value of i is used for a purpose other than to determine what value to store into i. – Robert Gamble Aug 26 '10 at 13:23
  • Any idea how this combines with OOE, or is that another level of abstraction? – Matt Joiner Aug 26 '10 at 14:25
  • @Matt: That's a layer of abstraction down. So long as you write correct C code, the result will be the same regardless of whether your platform does OOE or not. In fact, even if you write incorrect code, you should get the same result, because the binary executable is the same in each case. – Oliver Charlesworth Aug 26 '10 at 15:22
  • @Matt Joiner We need to add the caveat: *from the perspective of the context in which the thread is executed* to the excellent answer above. OOE is generally invisible to the instruction stream - the CPU's instruction scheduler has ensure that data dependencies between instructions are met. When it comes to the memory and caches, it's an entirely different story, and both the C and C++ standards are very specific about the need to use memory barriers if the order of completion as seen by memory is important. – marko Oct 16 '13 at 13:23
  • I understand variable cannot get updated more than once within a sequence point and hence i=i++ is undefined. But why b= i++ + i is also undefined? I get compiler warning for this too. – Rajesh Apr 01 '19 at 00:51
  • @Rajesh: it's beacuase `+` is not a sequence point so does not separate the `i++` modification and `i` usage. I see I haven't necessarily made it clear that usage is a broblem as well, not just modification. I'll clear that up. – paxdiablo Apr 01 '19 at 01:40
13

An important thing to note about sequence points is that they are not global, but rather should be regarded as a set of local constraints. For example, in the statement

a = f1(x++) + f2(y++);

There is a sequence point between the evaluation of x++ and the call to f1, and another sequence point between the evaluation of y++ and the call to f2. There is, however, no guarantee as to whether x will be incremented before or after f2 is called, nor whether y will be incremented before or after x is called. If f1 changes y or f2 changes x, the results will be undefined (it would be legitimate for the compiler's generated code to e.g. read x and y, increment x, call f1, check y against the previously-read value, and--if it changed--go on a rampage seeking out and destroying all Barney videos and merchandise; I don't think any real compilers generate code that would actually do that, alas, but it would be permitted under the standard).

supercat
  • 77,689
  • 9
  • 166
  • 211
  • If any function modified x or y then this is done after the sequence point(the one immediately before the actual call of the function). The behavior is unspecified. – 2501 Jun 03 '16 at 13:48
7

Expanding on paxdiablo's answer with an example.

Assume the statement

x = i++ * ++j;

There are three side effects: assigning the result of i * (j+1) to x, adding 1 to i, and adding 1 to j. The order in which the side effects are applied is unspecified; i and j may each be incremented immediately after being evaluated, or they may not be incremented until after both have been evaluated but before x has been assigned, or they may not be incremented until after x has been assigned.

The sequence point is the point where all side effects have been applied (x, i, and j have all been updated), regardless of the order in which they were applied.

John Bode
  • 119,563
  • 19
  • 122
  • 198
4

It means a compiler may do funky optimizations, tricks and magic but must reach a well-defined state at these so-called sequence points.

DarkDust
  • 90,870
  • 19
  • 190
  • 224