|
|
|
|
|
|
From my point of view, 1) should not be possible. '=' has the weakest precedence, meaning it connects the operands 'i' and '3*i++'. So before doing both, the multiplication and the incrementation, the assignment can't happen. |
cppreference wrote: |
---|
The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compound assignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (that is, before returning the reference to the modified object) — https://en.cppreference.com/w/cpp/language/eval_order |
P.S.: The rules have changed in C++17. |
|
|
|
|
|
|
|
|
|
|
|
|
I'm just gonna ramble here, but: Honestly, the "changing undefined behavior to unspecified behavior" thing just makes it more confusing. It still doesn't make the code portable. Plus, no sane person should write code like that even if they know how the compiler will handle it. They should have just gone all the way (removing obvious undefined behavior), or not changed it. |
Repeater wrote: |
---|
As an aside, speaking as an experienced C++ programmer, I don't care about operator precedence. I never learned it. I just write my code so it's clear what I intend to both reader and compiler. Memorising the tiny details of operator precedence is fun if you like that kind of thing, but if your aim is to be a better C++ programmer, you're wasting tim |
mbozzi wrote: |
---|
We'll have to distinguish between the different kinds of evaluations. When evaluating an expression: - if the expression has a value, its value maybe needs to be determined in a process called value computation. - if the expression has side-effects, those side effects maybe need to be started in a process called initiation of side-effects. Both of these processes are independent. When an expression is evaluated, we look at all the required value computations and side-effects together, and order them according to a relation called sequenced-before. This relation tells us that for some pairs of evaluations, one occurs before the other. For example, consider an ordering of a deck of cards by value, ignoring suit. We can't say that the six of clubs occurs before or after the six of hearts, but it certainly occurs before a seven of any suit. We'd say that such an relationship is a strict partial order. Similarly, C++'s sequenced-before relation only guarantees that some evaluations occur before some others. For example, in an expression containing i++, we've got a guarantee that the value of i++ is computed before the side-effect of i++ is initiated, which rules out case 3. |
But in the expression i = 3*i++, we don't have a guarantee that the side effect of the assignment happens before or after the side-effect of i++. It could happen either way. |
Why does this rule out 3)? I calculate i++. Then I save this value into i (which is the side effect, right?). Then I do my 3*i calculation... |
Ok. It just feels strange to me that the '=' groups together the whole righthand side but the actual assignment can happen BEFORE everything on the righthand side is 'done'. |
PhysicsIsFun wrote: |
---|
The book says there are two options: |
i = 3 * i++
was undefined: it had no meaning at all) or only one option (since C++17, where it is defined). What book was it?
i = 3 * i++;
, while outputting 6.
mbozzi wrote: |
---|
The computed value of an expression won't change retroactively. Imagine that the result is stored somewhere - so that when the value is required, it will be looked up instead of being value-computed again. |
mbozzi wrote: |
---|
This multiplication is like E1 * E2, where E2 takes the value of i and later increments i, and E1 has the value 3. That the value computation is sequenced before the side-effect is the difference between i++ and ++i. |
|
|
|
|
PhysicsIsFun wrote: |
---|
He does say that the behaviour is undefined, his reasoning being that there are two possibilities in what could happen there |