1

Please have a look at following code snippet:

int a = 10, b;  
b = (a) + (++a);                       //2  
printf("b = %d\n", b);  

Output:

b = 22  

In statement 2, there are 4 distinct operators. Out of which () has highest precedence. Since associativity of () operator is left to right why b = 22 and not 21 ?

$ gcc --version  
gcc (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3
rootkea
  • 1,474
  • 2
  • 12
  • 32
  • You are not allowed read and modify the same variable within a single sequence point. See [this C-faq question](http://c-faq.com/expr/evalorder1.html), and [sequence points in C](http://stackoverflow.com/q/3575350/315052). – jxh May 13 '13 at 20:01
  • What about `x = x + 1` ? Here `x` on RHS is read once and then the `x` on LHS side is used to modify it's value. And that's within single sequence point. The standard 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.". It says that you can't modify the variable more than once within a single variable. – rootkea May 13 '13 at 20:33
  • The next sentence of your quote is the difference in this case. See Keith Thompson's answer. – jxh May 13 '13 at 20:48

2 Answers2

8
b = (a) + (++a);

This has undefined behavior.

Quoting the C99 standard (actually the N1256 draft), 6.5p2:

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.

This expression both reads the value of a and updates it, and the read operation (the LHS of the +) is not used to determine the value to be stored by the write operation (the RHS of the +).

The 2011 ISO C standard (quoting from the N1570 draft) states this differently, but with essentially the same meaning:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

(a) is a value computation using the value of a; (a++) is a side effect on a. Since the order of evaluation of the operands of + is not specified, these two operations are unsequenced relative to each other.

So it's not just a matter of the order of evaluation being undefined -- the behavior is undefined, and is not limited to the possibilities of the operands of the + operator being evaluated in either of the two possible orders.

And no, the parentheses don't change this.

Section 3 of the comp.lang.c FAQ explains this well.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
3

The evaluation order of + is not specified.

taocp
  • 23,276
  • 10
  • 49
  • 62
  • Yes true. But that's for `a + b` and not for `(a) + (b)`. Correct me if I'm wrong. – rootkea May 13 '13 at 20:02
  • @rootkea: I don't follow. With `(a) + (b)` the compiler is free to choose the order of evaluation of the `(a)` and `(b)` subexpressions. – Nik Bougalis May 13 '13 at 20:05
  • @rootkea adding () to both a and b will not change the fact that evaluation order of the two operands of + is not specified. This post has better information:http://stackoverflow.com/questions/7112282/order-of-evaluation-of-operands – taocp May 13 '13 at 20:06
  • @NikBougalis- In `(a) + (b)` there are 3 operators. 2 `()` and 1 `+`. Now `()` has highest precedence and it's left to right associative. So `(a)` will get evaluated first followed by `(b)` – rootkea May 13 '13 at 20:10
  • 1
    @rootkea Precedence has nothing to do with order of evaluation. It just determines the shape of the expression tree (implicit parentheses). – Daniel Fischer May 13 '13 at 20:22
  • @rootkea what Daniel said... – Nik Bougalis May 13 '13 at 20:27
  • @rootkea: The parentheses in the expression (a) + (b) are not operators, so there is only one operator in the expression. It looks like you are thinking of the function-call operator, which is typically shown as a pair of parentheses in C precedence tables. – Thomas Padron-McCarthy Jul 01 '13 at 13:01