0

I have wrote follwing code in c

int x = 8;
x -= --x - x--;
printf("%d", x);

It is printing 6 but according to my logic statement should be converted to (right to left execution)

x = 6-6-8; 

and so the answer should be -8.

Can anyone say what is happening here?

Deleted User
  • 2,551
  • 1
  • 11
  • 18
Sumit P Makwana
  • 317
  • 5
  • 17

1 Answers1

3

It is undefined behaviour. The C99 standard §6.5 ¶2 says

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

x -= --x - x--;

// equivalent to
x = x - --x - x--;

// postfix decrement has higher precedence than
// prefix decrement. Both have higher precedence than
// subtraction operator. Therefore the above statement is
// equivalent to
x = x - (--x) - (x--);

// the subtraction associates from left to right 
// therefore the above statement is parsed as
x = (x - (--x)) - (x--);

Now, the important thing to note here is the evaluation of operands of - operator are unsequenced relative to each other. This means it is not fixed which sub-expression (x - (--x)) or (x--) will be evaluated first.

Quoting from this excellent article Order of evaluation from cppreference.com -

There is no concept of left-to-right or right-to-left evaluation in C, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression a + b + c is parsed as (a + b) + c due to left-to-right associativity of operator+, but the subexpression c may be evaluated first (or last, or at the same time as a or b) at run time.

Second important thing to note is in the above statement, the value of x is modified twice due to the side effect of the expression --x and x--. There is no sequence point between these the evaluation of these two expressions and hence it is not guaranteed when the side effects will take place. Therefore, with reference to the above part from the standard, it's undefined behaviour.

Combining the above two stated points the expression can evaluate to multiple values.

int x = 8;
x = (x - (--x)) - (x--);
//  (a)   (b)      (c)   name of the sub expressions

// assume (c) is evaluated first and side effect
// takes place immediately. Then (b) is evaluated and
// side effect takes place immediately

x = (6 - (6)) - (8);   // -8

// assume (a) is evaluated first, then (b)
// however the side effect of (b) does not take
// place before (c) gets evaluated          

x = (8 - (7)) - (7);   // -6      

These are just two examples to illustrate the different values x can have after the statement is executed. This should not be taken to mean that x will always have one of the values from all possible values. The standard says it's undefined behaviour which means that the behaviour is unpredictable. The standard imposes no requirements on the implementation to deal with such cases. Undefined behaviour means anything can happen from daemons flying out of your nose to your hard drive getting formatted. You should always avoid writing code which invokes undefined behaviour. For more details, please read this - Undefined Behavior and Sequence Points.

Community
  • 1
  • 1
ajay
  • 9,402
  • 8
  • 44
  • 71