Operator precedence

Hi guys, this is my first post.

I started reading in a C++ book and I have come across the tableau of operator precedence. Now it says that ++ has a higher precedence than = or *, but yet the book implies the following is ambigous:

1
2
  int i=2;
  i=3*i++;

The book says i could either become 6 or 7 in the end.
But according to the tableau, i should be incremented first, then multiplied with 3 and then given to i, so i should become 9.

What am I missing??

Regards
What am I missing??

A sequence point.

You are invoking Undefined Behavior when you try to increment "i" in the second line.

Your compiler may be able to warn you about the issue, here is what my compiler reports:

main.cpp warning: operation on ‘i’ may be undefined [-Wsequence-point]|

Edit: Forgot to mention the problem is not an operator precedence issue.
Last edited on
don't know what that is :(
sequence point.

Why is that logic flawed. I have a line with operations. If there is a clear priority list, it should be obvious what happens.
The book implies the following is ambigous

The book is too gentle: any program which contains that code is entirely wrong.

If there is a clear priority list, it should be obvious what happens.
Operator precedence and associativity doesn't have anything to do with order of evaluation.

Imagine I asked you to compute the following value:
(0.1 * 2.3) / (4.5 * 6.7) * (8 * 9)
Operator precedence does not compel you to evaluate all the parts of the problem in any particular order. If you so chose, you might compute the term (8 * 9) first, even though according to the binding order it's the "lowest-priority" term. Alternatively, you might attempt to simplify by computing (0.1 * 2.3) and (8 * 9) first, and then multiplying them - again, this doesn't concern operator precedence - it won't make any difference to the result.

The only thing operator precedence tells you is which operands belong to which operators.

Similarly, C++ offers limited guarantees regarding the evaluation order of terms (more specifically expressions and sub-expressions). In the case of the example you gave, there are no guarantees that the side effect implied by i++ happens before the side-effect implied by the assignment. That might happen before or after, or even in the middle of the assignment operation. In the jargon, we would say that such an expression implies two unsequenced side effects relative to the same object. This is undefined behavior.

Well, until C++17, which offers this guarantee:
In every simple assignment expression E1=E2 and every compound assignment expression E1@=E2, every value computation and side-effect of E2 is sequenced before every value computation and side effect of E1.
Last edited on
Hi mbozzi,

thanks für the reply, but I still don't see through this. In your example, I understand that there is no defined order in which I have to calculate the expressions, but I could just say: 'this is because all the operators in the whole expression (*, / ) have the same precedence, therefore it's ambiguous'

But in my example, where two operators with different precedence are present, the evaluation should be obvious. Still don't see the difference between order of evaluation and operator precedence.
This is not an evaluation order nor an operator precedence problem.

Let's simplify the problem to it's simplest term: i = i++; produces undefined behavior (assume i has been initialized to some value prior to this line).


jlb wrote:
This is not an evaluation order [...] problem

I disagree. Whether or not the above is well-defined depends on whether or not one of the modifications to i is sequenced before the other. Neither of them are (until C++17).

PhysicsIsFun wrote:
I could just say: 'this is because all the operators in the whole expression (*, / ) have the same precedence, therefore it's ambiguous'

Yes you could, but that's a fabrication. Try (0.1 + 2.3) / (4.5 + 6.7) + (8 + 9) instead. Still, the order in which you compute the values of the operands to any particular operator doesn't change the result of the expression.

The order in which you evaluate operands in this context is called evaluation order; these individual evaluations are unsequenced. C++ assumes that the programmer will not write code which relies on those operations occurring in any particular order.

Again, the only thing binding order tells the compiler is which operands belong to which operators. This information is entirely independent of the order in which it computes the values of those operands, and the order in which it evaluates the side-effects of those operands. With a few exceptions, C++ doesn't sequence those side-effects within expressions (i.e., it leaves them unsequenced), and that's the cause of the problem.

I'm trying to simplify this, but the details are here.
http://en.cppreference.com/w/cpp/language/eval_order
Last edited on
Thanks mbozzi,

I will go through the link later and come back here if I still have questions.
Topic archived. No new replies allowed.