After stumbling across the question "Why are these constructs using pre and post-increment undefined behavior?" today I decided to grab the newest draft for the next C standard I could find and read more about it.
Shortly after I discovered the following paragraph in a C17 draft:
An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof. The value computations of the operands of an operator are sequenced before the value computation of the result of the operator
Source: ISO/IEC 9899:2017, Section 6.5 §1 "Expressions" (link broken use web.archive.org)
Now I am a little confused. Doesn't that mean that i = i++
is defined behavior? I looked at another draft, C99 this time:
An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof.
Source: ISO/IEC 9899:1999, Section 6.5 §1 "Expressions"
It's missing that very sentence!
Note: this question is related, it's about C++ though.
The passage you highlighted only says that the expressions i++
and i
are evaluated before the evaluation of the full expression i = i++
. It is still undefined behavior because i
is being modified more than once in an expression without a sequence point.
That passage first appeared in C11, so there's no change from that version C17.
The full story. In C99 we had this text for 6.5.16 the assignment operator:
The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point.
The order of evaluation of the operands is unspecified. If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point, the behavior is undefined.
This was changed in C11 to:
The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
This is just different (and worse) wording, the two versions behave the same - the key being the last sentence in the C11 part which still makes this undefined behavior, since evaluation of the left operand is still unsequenced in relation to the right operand. Value computation just refers to the individual operands.
C17 has identical text as C11. So the answer is: no, i = i++;
is still undefined behavior in C17.
Just for reference, compare this with C++11 (5.17):
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
This is roughly the same text as C11, without the explicit "the evaluations of the operands are unsequenced". This was a flaw in C++11, it isn't clear if this would make certain expressions well-defined or not.
C++17 provides a clarification (8.5.18):
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. The right operand is sequenced before the left operand.
So in C++17, i=i++;
is definitely well-defined. And as we can see, the wording is explicit, as opposed to "unsequenced" in C11/C17.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With