Sequence points versus operator priority

Possible duplicate:
Inconsistent value calculations (aka sequence points)
Undefined Behavior and Sequence Points
Operator Priority and Evaluation Order

I'm still trying to circle my head as the following expression leads to undefined behavior:

a = a++; 

After searching SO about this, I found the following question:

Difference between sequence points and operator priority? 0_o

I have read all the answers, but I am still having difficulty with the details. One answer describes the behavior of my above code example as ambiguous in terms of changing a . For example, this may result in one of the following:

 a=(a+1);a++; a++;a=a; 

What exactly makes modification a ambiguous? This is due to processor instructions on different platforms, and how can the optimizer use undefined behavior? In other words, it seems undefined due to the generated assembler?

I do not see the reason the compiler uses a=(a+1);a++; He just looks freaky and doesn't make much sense. What will the compiler have to make it behave this way?

EDIT:

Just to be clear, I understand what is happening, I just don’t understand how it can be undefined when there are rules about the priority of the operator (which essentially determines the evaluation order of the expression). In this case, the assignment is the last, so first you need to evaluate the value of a++ in order to determine the value for assignment a . So I expect that a first changes during the increment after the fix, but then gives a value to reassign a (second modification). But the rules for operator precedence seem to make the behavior very clear to me, I can’t find where there is any kind of “fly-in” to have undefined behavior.

+7
source share
6 answers

The first answer in the question that you linked to explains what exactly is happening. I will try to rephrase it to make it more understandable.

The priority of the operator determines the order in which the values ​​are calculated using expressions. The result of the expression (a++) well understood.

However , modifying the variable a not part of the expression. Yes indeed. This is the part with which you have trouble understanding, but it's just how C and C ++ define it.

Expressions lead to meanings, but some expressions can have side effects. The expression a = 1 has the value 1 , but also has the side effect of setting the variable a to 1 . As far as C and C ++ define things, these are two different steps. Similarly, a++ has a side effect.

Sequence points determine when side effects are visible to expressions that are evaluated after these sequence points. Operator priority has nothing to do with sequence points. This is how C / C ++ defines things.

+8
source

This is probably an oversimplified explanation, but I think it is because there is no way to decide when the code is "done" with "a". Is this done after the increment or assignment? Resolution ends in a circular. Assignment after an increment changes semantics when an increment is applied. That is, the code is not executed with "a" until "a" is incremented, but a is not incremented until the assignment is made. This is an almost language version of the dead end.

As I said, I'm sure this is not a great “academic” explanation, but the way I brew it between my ears. Hope this helps.

+1
source

The priority rules indicate the order in which expressions are evaluated, but side effects should not occur during the evaluation. They can occur at any time to the next point in the sequence.

In this case, the side effect of the increment is sequenced neither before nor after the assignment, so the expression has undefined behavior.

+1
source

The point here is that on some processor architectures, such as Intel Itanium, these two operations can be parallelized by the compiler at the command level, but for your design to be clearly defined, this will be prohibited. At the time of specifying the endpoint, these architectures were mostly hypothetical, and since Itanium was a flop, it can be argued that since 2012, most of this is not unnecessary complexity in the language. Basically, there is no flaw in any architecture that is still used in normal mode, and even for Itanium the performance advantage was minimal, and the headache in writing a compiler that could even use it was huge.

Also note that in C ++ 11, point sequences were replaced by sequenced ones before and after sequences, which made more situations like this one clearly defined.

0
source

This a=a++ operator has two results and two purposes:

 a=a 

(because its post-increment) And

 a=a+1 

These assignments clearly lead to a different final meaning for a .

The developers of the c standard did not indicate which of the two assignments should be written to a first, and secondly, so the authors of the compilers can choose depending on what they like in any given situation.

Result: it (this particular operator) will not break, but your program can no longer rely on a specific value.

0
source

Let me complete the main task in the a = a++ statement. We want to achieve the following goals:

  • determine the value of a (return value a++ , # 1)

  • increment a (side effect a++ , # 2)

  • set the old value a (assignment effect, No. 3)

There are two possible ways this could be sequenced:

  • Save the original a in a (no-op); then increment a . Same as a = a; ++a; a = a; ++a; . This is the sequence # 1- # 3- # 2.

  • Evaluate a , increment a , return the original value of a . Same as b = a; ++a; a = b; b = a; ++a; a = b; . This is the sequence # 1- # 2- # 3.

Since there is no prescribed sequence, any of these operations is valid. But they have a different end result. None of these sequences is more natural than the other.

0
source

All Articles