Undefined Behaviour

Eric Bailey

Written on 7 May, 2018
Updated on 26 August, 2024
Tags: , , ,

A friend at work today was telling me about his wife's C​++ class, wherein the students were asked to predict the behaviour of the following snippet.

x = 10;
y = ++x + --x;

Example

For simplicity, let's assume the type of both x and y is int.

int x, y;

We can inspect the final state of x and y with a simple printf call.

printf("x = %d, y = %d\n", x, y);

Now, let's see how different compilers handle our program.

#include <stdio.h>


int main(int argc, char **argv)
{
    int x, y;
    x = 10;
    y = ++x + --x;

    printf("x = %d, y = %d\n", x, y);
}

At first glance, I would expect the right-hand side of the initialization of y to evaluate to 11 + 10, i.e., 21.

gcc (GCC) 13.2.0

incdec.c: In function ‘main’:
incdec.c:8:9: warning: operation on ‘x’ may be undefined [-Wsequence-point]
    8 |     y = ++x + --x;
      |         ^~~

x = 10, y = 20

Curiouser and curiouser!

Unsurprisingly, GCC computes the final value of x to be 10, the same as its initial value, after being incremented and decremented. It's markedly less intuitive to me that the final value of y is 20.

Clang, on the other hand, agrees with me, i.e., computes the final value of y to be 21.

clang version 17.0.6

incdec.c:8:9: warning: multiple unsequenced modifications to 'x' [-Wunsequenced]
    8 |     y = ++x + --x;
      |         ^     ~~
1 warning generated.

x = 10, y = 21

The more you know

Both compilers warn about unsequenced modifications and the resultant undefined behaviour. Digging around a bit leads to some fascinating discussions. The GCC team maintains a list of further reading, including a few formal models and analyses of sequence points in C. Further exploration is left as an exercise for the reader.

tl;dr

It is not specified when between sequence points modifications to the values of objects take effect.

The standard is worded confusingly, therefore there is some debate over the precise meaning of the sequence point rules in subtle cases.