Why does the following compile in C++?
int phew = 53;
++++++++++phew ;
The same code fails in C, why?
Why does the following compile in C++?
int phew = 53;
++++++++++phew ;
The same code fails in C, why?
That is because in C++
pre-increment operator returns an lvalue
and it requires its operand to be an lvalue
.
++++++++++phew ;
in interpreted as ++(++(++(++(++phew))))
However your code invokes Undefined Behaviour
because you are trying to modify the value of phew
more than once between two sequence points.
In C
, pre-increment operator returns an rvalue
and requires its operand to be an lvalue
. So your code doesn't compile in C mode.
Commentary
This specification only needs to be followed exactly when there is more than one access between sequence points, or for objects declared with the volatile storage class. As far as the developer is concerned, a modification occurs. As long as the implementation delivers the expected result, it is free to do whatever it likes. –
Whitcomb ++++i
is well-defined for user-defined types, right? –
Skillful int & f( int & x ) { return ++x; }
and the call: int x = 0; f( f( f( x ) ) );
The inner f
must be executed before the middle f
and that is guaranteed to be performed before the external f
call. The semantics if pre-increment require the increment to be performed before the value is yielded. On the other hand, int x = 0; int y = ++x + x++;
is undefined as the relative order of execution of the pre and post increment undefined. –
Billy operator++
, and then to apply optimisations to the result as if it were a single expression, without somehow annotating the inlined code to retain the sequence point. It's a fairly fundamental error, since if you got it wrong in this case I bet the optimiser would incorrectly coalesce/reorder statements in other cases too, but I think it's an omission rather than a comission... –
Semivitreous Note: The two defect reports DR#637 and DR#222 are important to understand the below's behavior rationale.
For explanation, in C++0x there are value computations
and side effects
. A side effect for example is an assigment, and a value computation is determining what an lvalue refers to or reading the value out of an lvalue. Note that C++0x has no sequence points anymore and this stuff is worded in terms of "sequenced before" / "sequenced after". And it is stated that
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
++v
is equivalent to v += 1
which is equivalent to v = v + 1
(except that v is only evaluated once). This yields to ++ (v = v + 1)
which I will write as inc = inc + 1
, where inc
refers to the lvalue result of v = v + 1
.
In C++0x ++ ++v
is not undefined behavior because for a = b
the assignment is sequenced after value computation of b and a, but before value computation of the assignment expression. It follows that the asignment in v = v + 1
is sequenced before value computation of inc
. And the assignment in inc = inc + 1
is sequenced after value computation of inc
. In the end, both assignments will thus be sequenced, and there is no undefined behavior.
int a=4; ++a=5;
would not invoke UB in C++0x, right? –
Whitcomb a
to 5. Likewise a = ++a;
will not be UB, but a = a++;
will be UB. –
Goode int a=4,b; b = a + a++ ;
, that would be UB or not. Lets see, addition of a
and a++
is sequenced before assignment, but hey order of evaluation is still unspecified, is it?. Phew! this is confusing. –
Whitcomb a = ++a
does not invoke undefined behavior, but a = a++
does. What happened to "except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified"? –
Elongate a++
, the previous value of "a" is accessed to determine the value being stored, so C++0x induces an order into this. But for "a + a++", this is not the case with respect to the first "a", so it's not ordered and it becomes undefined. This shows a strong point of the C++0x wording. It's much more reliable. –
Goode a = ++a
and ++ ++ a
is defined behavior and is intended to be so. –
Goode DR637
to James Kanze
who made all of us(excluding you) think that he was right all the time. :-)
–
Whitcomb ++++v
to be well defined is not convincing. C++11 says that: The side effect of the built-in preincrement and predecrement operators is sequenced before its value computation. and that make more sense in this case. –
Unknowable ++++v
is well defined is seem confusing to me. As per your explanation i = ++i
would be well defined (which is not) in C11 too because it says that: An assignment expression has the value of the left operand after the assignment. –
Unknowable a=++a
would invoke UB in c++11,since the modification in "++a" and the value computation in "a"(the left hand operand) relative to each other are unsequenced,so ,theres' no value computation for single a
,Do you agree? –
Eller That is because in C++
pre-increment operator returns an lvalue
and it requires its operand to be an lvalue
.
++++++++++phew ;
in interpreted as ++(++(++(++(++phew))))
However your code invokes Undefined Behaviour
because you are trying to modify the value of phew
more than once between two sequence points.
In C
, pre-increment operator returns an rvalue
and requires its operand to be an lvalue
. So your code doesn't compile in C mode.
Commentary
This specification only needs to be followed exactly when there is more than one access between sequence points, or for objects declared with the volatile storage class. As far as the developer is concerned, a modification occurs. As long as the implementation delivers the expected result, it is free to do whatever it likes. –
Whitcomb ++++i
is well-defined for user-defined types, right? –
Skillful int & f( int & x ) { return ++x; }
and the call: int x = 0; f( f( f( x ) ) );
The inner f
must be executed before the middle f
and that is guaranteed to be performed before the external f
call. The semantics if pre-increment require the increment to be performed before the value is yielded. On the other hand, int x = 0; int y = ++x + x++;
is undefined as the relative order of execution of the pre and post increment undefined. –
Billy operator++
, and then to apply optimisations to the result as if it were a single expression, without somehow annotating the inlined code to retain the sequence point. It's a fairly fundamental error, since if you got it wrong in this case I bet the optimiser would incorrectly coalesce/reorder statements in other cases too, but I think it's an omission rather than a comission... –
Semivitreous © 2022 - 2024 — McMap. All rights reserved.