I read this answer about undefined behaviour, where I saw following statement:
++++++i; // UB, parsed as (++(++(++i)))
I don't think it is undefined behaviour. I have a doubt, Is it really UB in C++? If yes, then How?
Also, I made program and compiled using g++ prog.cpp -Wall -Wextra -std=gnu++1z -pedantic command, it's working fine without any warning. It's give an expected output.
#include <iostream>
using namespace std;
int main()
{
int i = 0;
cout<<++++++i<<endl;
}
In C++03 it is undefined behavior. In C++11 it is not. There is no sequence point between the various pre-increments. If i was a user-defined type, it would be well-defined behavior because then there would be a function call (a sequence point).
In C++11, the idea of sequence points was replaced with sequenced before/sequenced after. Defect 637 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637) provides an example of a previously undefined construct becoming well-defined (i = ++i + 1).
To understand why it's not undefined behavior, let's look at the pieces we need. ++i is equivalent to i = i + 1 (except i is evaluated only once). Further if we substitute i = i + 1 with inc, ++(i = i + 1) becomes inc = inc + 1.
[expr.ass] states:
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.
Thus the assignment in i = i + 1 is sequenced before value computation of inc; however, the assignment in inc = inc + 1 is sequenced after value computation of inc. There is no undefined behavior because the assignments are sequenced.
Sometimes behavior is undefined even though it's hard to imagine how it could be mishandled. But pre-C++11, this was undefined because the same object is modified multiple times without an intervening sequence pointed.
One could imagine a compiler that "optimized" the code by consolidating all the modifications to i. Thus each increment winds up incrementing the original value. But that's not the point. UB is UB if the standard says so. It doesn't matter whether or not we can imagine ways it can fail.
Related
In this answer there're some examples of well-defined and undefined expressions. I'm particularly interested in two of them:
(6) i = i++ + 1; // Undefined Behaviour
(7) i = ++i + 1; // Well-defined Behaviour
This means that there's a difference between pre-increment and post-increment in terms of sequence points and well defined /unspecified/undefined behavior, but I don't understand where this difference comes from.
In standard draft (N4618) there's an example of code ([intro.execution], pt 18)
i = i++ + 1; // the value of i is incremented
i = i++ + i; // the behavior is undefined
Which, as far as I understand, means that expression i = i++ + 1 should be well-defined and the value of a variable i should increase by 1 as the result of this expression. However, this code run in MSVS 2015 increases i by 2.
So, what happens in the expression i = i++ + 1? Is it well-defined, undefined, implementation-defined or unspecified behavior? And is there any difference between pre-increment and post-increment in this and similar expressions in terms of sequence points and UB, as stated in the original answer? And why Visual Studio shows the behavior which is different from written in standard?
Please also note that I'm primarily interested in modern c++ (14/17).
What happens in the expression i = i++ + 1? Is it well-defined, undefined, implementation defined or unspecified behaviour?
This exact example is given in the standard, how lucky are we?
N4296 1.9.15 [intro.execution]
i = i++ + 1; // the behavior is undefined
Of course, we'd like to know why too. The following standard quote appears to be relevant here:
N4296 1.9.15 [intro.execution]
[ ... ] The value computations of the operands of an operator are sequenced
before the value computation of the result of the operator. [ ... ]
This tells us that the sum will occur before the assignment (duh, how else does it know what to assign!), but it doesn't guarantee that the increment will occur before or after the assignment, now we're in murky water...
N4296 1.9.15 [intro.execution]
[ ... ] 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, and they are not
potentially concurrent (1.10), the behavior is undefined. [ ... ]
The assignment operator has a side effect on the value of i, which means we have two side effects (the other is the assignment performed by i++) on the same scalar object, which are unsequenced, which is undefined.
Why does Visual Studio show the behavior which is different from written in standard?
It doesn't. The standard says it's undefined, which means it can do anything from what you wanted to something completely different, it just so happens that this is the behaviour that got spat out by the compiler!
i = ++i + 1; // Well-defined Behaviour
This means that there's a difference between preincrement and postincrement in terms of sequence points and well defined / unspecified / undefined behavior, but I don't understand where this difference comes from.
I believe that post is incorrect in several ways. Quoting the same section as they do, emphasis mine:
C++11 1.9/15
The value computations of the operands of an
operator are sequenced before the value computation of the result of the operator. 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.
Then the assignment operator:
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.
Notable, the value computation or the right and left operands is not sequenced. (This has been explicitly spelled out in C11 1), which otherwise has a completely identical text as C++11.)
Meaning that in the expression i = ++i + 1; the side effect of ++i is unsequenced in relation to the value computation of the left operand i. Thus it is undefined behavior as per 1.9/15. And the UB has nothing to do with the assignment side-effect at all.
As for the expression i = i++ + 1;, the side-effect of assignment is, as per C++11, explicitly sequenced after the value computations, but before the value computation of the expression as whole. The value computation of i++ is not an issue as per 5.2.6 "The value computation of the ++ expression is sequenced before the modification of the operand object". As per the nature of the postfix ++, the side effect of updating i++ must be sequenced after the value computation of the whole expression. It is well-defined behavior, as far as I can tell.
Correct text should therefore be
(6) i = i++ + 1; // Well-defined Behaviour
(7) i = ++i + 1; // Undefined Behaviour
Apparently there was an incorrect example in C++11 1.9/15 i = i++ + 1; // the behavior is undefined which has been corrected in later versions of the standard.
NOTE: None of this has the slightest to do with the change of wording about sequence points!
1) C11 6.5.16/3
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 question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
#include <iostream>
using namespace std;
main(){
int i = 5;
cout << i++ << i--<< ++i << --i << i << endl;
}
The above program compiled with g++ gives output :
45555
While the following program:
int x=20,y=35;
x =y++ + y + x++ + y++;
cout << x<< endl << y;
gives result as
126
37
Can anyone please explain the output.
cout << i++ << i--
is semantically equivalent to
operator<<(operator<<(cout, i++), i--);
<------arg1--------->, <-arg2->
$1.9/15- "When calling a function
(whether or not the function is
inline), every value computation and
side effect associated with any
argument expression, or with the
postfix expression designating the
called function, is sequenced before
execution of every expression or
statement in the body of the called
function. [ Note: Value computations
and side effects associated with
different argument expressions are
unsequenced. —end note ]
C++0x:
This means that the evaluation of the arguments arg1/arg2 are unsequenced (neither of them is sequenced before the other).
The same section in the draft Standard also states,
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.
Now there is a sequence point at the semicolon at the end of the full expression below
operator<<(operator<<(cout, i++), i--);
^ the interesting sequence point is right here
As is clear, evaluation of both arg1 and arg2 lead to side effect on the scalar variable 'i', and as we saw above, the side effects are unsequenced.
Therefore the code has undefined behavior. So what does that mean?
Here is how 'undefined behavior' is defined :) in the Standard.
Permissible undefined behavior ranges
from ignoring the situation completely
with unpredictable results, to
behaving during translation or program
execution in a documented manner
characteristic of the environment
(with or without the issuance of a
diagnostic message), to terminating a
translation or execution (with the
issuance of a diagnostic message).
Many erroneous program constructs do
not engender undefined behavior; they
are required to be diagnosed.
Do you see correlation with #DarkDust's response 'The compiler is even allowed to set your computer on fire :-)'
So any output you get from such a code is really in the dreaded realm of undefined behavior.
Don't do it.
Only thing that is defined about such code is that it helps OP and many of us get lots of votes (if answered correctly) :)
The result of the second program's expression is undefined. The compiler is even allowed to set your computer on fire :-) You're not allowed to modify a variable twice within one sequence point (in this case: from = to ;).
Edit:
For detailed explanations, see the C FAQ, specifically question 3.2.
Adding to other's answers:
If you are using g++, using the -Wsequence-point option tells that:
$ g++ -Wsequence-point a.cpp
a.cpp: In function ‘int main()’:
a.cpp:8: warning: operation on ‘i’ may be undefined
^^^^^^^^^
Undefined behaviour, so anything could happen
I can't find a definitive answer for this: does the following code have undefined behavior?
int x = 2;
x+=x+=x+=2.5;
The behavior is undefined. Let's look at the slightly simpler expression:
x += (x+=1)
In C++11, the value computation of the left x is unsequenced relative to the value computation of the expression (x+=1). This means that value computation of x is unsequenced relative to the assignment to x (due to x+=1), and therefore the behavior is undefined.
The reason for this is that the value computation of the two sides of the += operator are unsequenced relative to each other (as the standard doesn't specify otherwise). And 1.9p15 states:
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.
In C++03 the behavior is undefined because x is modified twice without an intervening sequence point.
For standard quotes see the other answers. It is likely to find one of two different behaviours in this case.
x += (x += 2);
May either be
x = 2 + 4 (= 6)
if the value of x on left side is evaluated before x+=2 or
x = 4 + 4 (= 8)
if the value of x for the left operator is determined afterwards.
-edit-
I know I not gonna get many fans on SO if I say I don't like those "anything may happen" claims very much.
It is true that any compiler can declare itself standard conformant regardless of how the statement we discuss here is handled with respect to the value of x. Nevertheless, I think it doesn't mean that operator += may result in a wrong result or that parantheses may be ignored.
Undefined behaviour is not the same as undefined behaviour in any other case.
It is bad to back on any expectation regarding undefined behaviour but in the above example i see good reasons for neglecting any possible outcome but 6 and 8.
In addition I actually suspect x to be 8 after the evaluation of int x=2; x += (x += 2); for most of the established compilers (clang, g++, vc, icpc...).
It is to be said again that you shouldn't rely on such behaviour but that doesn't mean that it is completely unpredictable.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
According to c++ standard,
i = 3;
i = i++;
will result in undefined behavior.
We use the term "undefined behavior" if it can lead to more then one result. But here, the final value of i will be 4 no matter what the order of evaluation, so shouldn't this really be called "unspecified behavior"?
The phrase, "…the final value of i will be 4 no matter what the order of evaluation…" is incorrect. The compiler could emit the equivalent of this:
i = 3;
int tmp = i;
++i;
i = tmp;
or this:
i = 3;
++i;
i = i - 1;
or this:
i = 3;
i = i;
++i;
As to the definitions of terms, if the answer was guaranteed to be 4, that wouldn't be unspecified or undefined behavior, it would be defined behavior.
As it stands, it is undefined behaviour according to the standard (Wikipedia), so it's even free to do this:
i = 3;
system("sudo rm -rf /"); // DO NOT TRY THIS AT HOME … OR AT WORK … OR ANYWHERE.
No, we don't use the term "undefined behavior" when it can simply lead to more than one arithmetical result. When the behavior is limited to different arithmetical results (or, more generally, to some set of predictable results), it is typically referred to as unspecified behavior.
Undefined behavior means completely unpredictable and unlimited consequences, like formatting the hard drive on your computer or simply making your program to crash. And i = i++ is undefined behavior.
Where you got the idea that i should be 4 in this case is not clear. There's absolutely nothing in C++ language that would let you come to that conclusion.
In C and also in C++, the order of any operation between two sequence points is completely up to the compiler and cannot be dependent on. The standard defines a list of things that makes up sequence points, from memory this is
the semicolon after a statement
the comma operator
evaluation of all function arguments before the call to the function
the && and || operand
Looking up the page on wikipedia, the lists is more complete and describes more in detail. Sequence points is an extremely important concept and if you do not already know what it means, you will benefit greatly by learning it right away.
1.
No, the result will be different depending on the order of evaluation. There is no evaluation boundary between the increment and the assignment, so the increment can be performed before or after the assignment. Consider this behaviour:
load i into CX
copy CX to DX
increase DX
store DX in i
store CX in i
The result is that i contains 3, not 4.
As a comparison, in C# there is a evaluation boundary between the evaulation of the expression and the assignment, so the result will always be 3.
2.
Even if the exact behaviour isn't specified, the specification is very clear on what it covers and what it doesn't cover. The behaviour is specified as undefined, it's not unspecified.
i=, and i++ are both side effects that modify i.
i++ does not imply that i is only incremented after the entire statement is evaluated, merely that the current value of i has been read.
As such, the assignment, and the increment, could happen in any order.
This question is old, but still appears to be referenced frequently, so it deserves a new answer in light of changes to the standard, from C++17.
expr.ass Subclause 1 explains
... the assignment is sequenced after the value computation of the right and left operands ...
and
The right operand is sequenced before the left operand.
The implication here is that the side-effects of the right operand are sequenced before the assignment, which means that the expression is not addressed by the provision in [basic.exec] Subclause 10:
If a side effect on a memory location ([intro.memory]) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent ([intro.multithread]), the behavior is undefined
The behavior is defined, as explained in the example which immediately follows.
See also: What made i = i++ + 1; legal in C++17?
To answer your questions:
I think "undefined behavior" means that the compiler/language implementator is free to do whatever it thinks best, and no that it could lead to more than one result.
Because it's not unspecified. It's clearly specified that its behavior is undefined.
It's not worth it to type i=i++ when you could simply type i++.
I saw such question at OCAJP practice test.
IntelliJ's IDEA decompiler turns this
public static int iplus(){
int i=0;
return i=i++;
}
into this
public static int iplus() {
int i = 0;
byte var10000 = i;
int var1 = i + 1;
return var10000;
}
Create JAR from module, then import as library & inspect.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
#include <iostream>
using namespace std;
main(){
int i = 5;
cout << i++ << i--<< ++i << --i << i << endl;
}
The above program compiled with g++ gives output :
45555
While the following program:
int x=20,y=35;
x =y++ + y + x++ + y++;
cout << x<< endl << y;
gives result as
126
37
Can anyone please explain the output.
cout << i++ << i--
is semantically equivalent to
operator<<(operator<<(cout, i++), i--);
<------arg1--------->, <-arg2->
$1.9/15- "When calling a function
(whether or not the function is
inline), every value computation and
side effect associated with any
argument expression, or with the
postfix expression designating the
called function, is sequenced before
execution of every expression or
statement in the body of the called
function. [ Note: Value computations
and side effects associated with
different argument expressions are
unsequenced. —end note ]
C++0x:
This means that the evaluation of the arguments arg1/arg2 are unsequenced (neither of them is sequenced before the other).
The same section in the draft Standard also states,
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.
Now there is a sequence point at the semicolon at the end of the full expression below
operator<<(operator<<(cout, i++), i--);
^ the interesting sequence point is right here
As is clear, evaluation of both arg1 and arg2 lead to side effect on the scalar variable 'i', and as we saw above, the side effects are unsequenced.
Therefore the code has undefined behavior. So what does that mean?
Here is how 'undefined behavior' is defined :) in the Standard.
Permissible undefined behavior ranges
from ignoring the situation completely
with unpredictable results, to
behaving during translation or program
execution in a documented manner
characteristic of the environment
(with or without the issuance of a
diagnostic message), to terminating a
translation or execution (with the
issuance of a diagnostic message).
Many erroneous program constructs do
not engender undefined behavior; they
are required to be diagnosed.
Do you see correlation with #DarkDust's response 'The compiler is even allowed to set your computer on fire :-)'
So any output you get from such a code is really in the dreaded realm of undefined behavior.
Don't do it.
Only thing that is defined about such code is that it helps OP and many of us get lots of votes (if answered correctly) :)
The result of the second program's expression is undefined. The compiler is even allowed to set your computer on fire :-) You're not allowed to modify a variable twice within one sequence point (in this case: from = to ;).
Edit:
For detailed explanations, see the C FAQ, specifically question 3.2.
Adding to other's answers:
If you are using g++, using the -Wsequence-point option tells that:
$ g++ -Wsequence-point a.cpp
a.cpp: In function ‘int main()’:
a.cpp:8: warning: operation on ‘i’ may be undefined
^^^^^^^^^
Undefined behaviour, so anything could happen