문제

Consider the C code a = a = a. There's no sequence point for assignment, so this code produces a warning when compiling about an undefined operation on a.

What are the possible values that a could have here? It seems like a couldn't possibly change values. Is there actually undefined behavior here or are compilers just being lazy?

도움이 되었습니까?

해결책

The rules of undefined behavior for sequence point violations do not make an exception for situations when "the value cannot change". Nobody cares whether the value changes or not. What matters is that when you are making any sort of write access to the variable, you are modifying that variable. Even if you are assigning the variable a value that it already holds, you are still performing a modification of that variable. And if multiple modifications are not separated by sequence points, the behavior is undefined.

One can probably argue that such "non-modifying modifications" should not cause any problems. But the language specification does not concern itself with such details. In language terminology, again, every time you are writing something into a variable, you are modifying it.

Moreover, the fact that you use the word "ambiguous" in your question seems to imply that you believe the behavior is unspecified. I.e. as in "the resultant value of the variable is (or isn't) ambiguous". However, in sequence point violations the language specification does not restrict itself to stating that the result is unspecified. It goes much further and declares the behavior undefined. This means that the rationale behind these rules takes into consideration more than just an unpredictable final value of some variable. For example, on some imaginary hardware platform non-sequenced modification might result in invalid code being generated by the compiler, or something like that.

다른 팁

This is actually undefined behavior. a can have any value at all. "I can't think of any way it can break" is not the same as "it's guaranteed to work".

It is actually the entire program that has "undefined behaviour" after it executes that statement. It's not just about the value of a - the program can do anything, including go into an endless loop, print garbage output or crash.

"Undefined behaviour" really just means that the C standard no longer places any limits on what the program does. That doesn't stop you reasoning about how a particular compiler might behave when it sees that code, but it's still not a valid C program, and that's what the compiler is warning you about.

int a = 42;
a = a = a;

is undefined behavior.

Sequence point rules were written to ease the work of compiler makers.

The C standard does not have a rule that says “If the behavior would be ambiguous, then the behavior is undefined.” The actual rule in C 1999 at issue 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. Furthermore, the prior value shall be read only to determine the value to be stored.”

Your code violates this rule: It modifies the value of a. (The note at 3.1 3 says that “Modify” includes the case where the new value being stored is the same as the previous value.)

So that is it. It does not matter whether you can figure out an unambiguous interpretation for this code. It only matters that it violated the rule. Because it violated the rule, the behavior is undefined.

In C 2011, the rule is stated in a more technical way. 6.5 2 says “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.” When the assignment operator stores a value in an object, that is actually a side effect. (The main effect is that it evaluates to the value that is stored.) So this rule in C 2011 says largely the same thing as the C 1999 rule: You may not have two side effects on the same object.

It's quite likely that you end up with the desired behavior. When somebody write a=a=a he probably desire a to be unchanged and when he writes a=a=b he probably desire a to be changed to b by the end of the statement.

However there are thinkable combinations of hardware and software that indeed breaks this assumption. Consider for example hardware where you have an explicit parallel instruction stream. The double assignment could then be compiled to two instructions trying to store data simultaneously in the same register. Furthermore the hardware designer could also have done the assumption that instruction pairs doing that is not allowed and could use don't-care values for those cases (and simplifying the HW).

Then you could actually end up in a situation where a=a=a actually changes the value of a and a=a=b ends up in a not being equal to b.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top