Purpose and sequence points: how is this ambiguous?

Consider the code C a = a = a . There is no sequence point for the assignment, so this code generates a warning when compiling about the operation undefined on a .

What are the possible meanings a can have here? It seems that a cannot change the values. Are there any undefined behavior here or are compilers just lazy?

+3
source share
6 answers

The rules of behavior undefined for violations of the sequence of points do not make an exception for situations where the value cannot be changed. No one cares whether the value changes or not. The important thing is that when you do any write access to a variable, you change that variable. Even if you assign a value to a variable that it already has, you still modify that variable. And if several modifications are not separated by sequence points, the behavior is undefined.

It can probably be argued that such “modifications without modification” should not cause any problems. But the language specification does not concern such details. In the terminology of the language, again, every time you write something to a variable, you change it.

Moreover, the fact that you use the word “ambiguous” in your question seems to imply that you think the behavior is unspecified. That is, because in the "resulting value of the variable (or not) is ambiguous." However, in case of violations of the sequence of characters, the language specification is not limited to the statement that the result is not specified. It goes much further and declares undefined behavior. This means that the rationale for these rules takes into account not just the unpredictable final value of a variable. For example, on some imaginary hardware platform, disjoint modifications can lead to invalid code generated by the compiler, or something like that.

+3
source

This behavior is undefined. a may have any meaning. "I can’t think about how it can break" - this is not the same as "it is guaranteed to work."

+2
source

In fact, the entire program that has "undefined behavior" after executing this statement. This is not only the value of a - the program can do something, including go into an endless loop, print garbage collection, or crash.

"undefined behavior" really just means that the C standard no longer limits what the program does. This does not stop you from discussing how a particular compiler can behave when it sees this code, but it is still not a valid C program, and what the compiler warns about.

+2
source
 int a = 42; a = a = a; 

- undefined behavior.

Sequence point rules were written to facilitate the work of compiler creators.

+1
source

There is no rule in the C standard that states: "If the behavior is ambiguous, then the behavior is undefined." The actual rule in Release C of 1999 states: "Between the previous and next points in the sequence, an object must have a stored value no more than once, evaluating the expression. In addition, the previous value should only be read to determine the value that should be stored."

Your code violates this rule: it changes the value of a . (The note in 3.1-3 says that “Modify” includes the case where the new stored value matches the previous value.)

That's all. It doesn't matter if you can understand the unambiguous interpretation of this code. The fact is that it violates the rule. Since this violates the rule, the behavior is undefined.

In C 2011, this rule is indicated in a more technical way. 6.5 2 says: "If the side effect of a scalar object is independent of another side effect for the same scalar object or calculating a value using the value of the same scalar object, the behavior is undefined. If there are several valid ordering subexpressions of an expression, the behavior is undefined, if such a side effect does not have a side effect in any of the orderings. " When an assignment operator stores a value in an object, this is actually a side effect. (The main effect is that it evaluates the value that is saved.) Thus, this rule in C 2011 says basically the same as rule C 1999: you may not have two side effects for the same object.

0
source

Most likely, you will get the desired behavior. When someone writes a=a=a , he probably wants a stay the same, and when he writes a=a=b , he probably wants a be changed to b by the end of the instruction.

However, there are conceivable combinations of hardware and software that really violate this assumption. Consider, for example, hardware, where you have an explicit parallel flow of commands. Then the dual purpose can be compiled into two instructions that try to store data at the same time in the same register. In addition, the hardware designer could also make the assumption that pairs of instructions that do this are not allowed and may use insecure values ​​for these cases (and simplify the HW).

Then you can really find yourself in a situation where a=a=a really changes the value of a and a=a=b ends with a not equal to b .

0
source

Source: https://habr.com/ru/post/947819/


All Articles