This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Operator Precedence vs Order of Evaluation
(6 answers)
Closed 9 years ago.
In order to find out what happened at the expression "i++ + i++ + i++ + i++", I wrote a test program as below.
compile it with g++ 4.6.3 and running this program under Ubuntu 12.04, the result are:
construct 3
construct 7
construct 12
construct 18
construct novalue
call i++ for 18
call i++ for 12
call i++ for 7
call i++ for 3
call + for 3 and 7
call + for 10 and 12
call + for 22 and 18
i1++ + i2++ + i3++ + i4++ : 4 8 13 19 40
construct 3
call i++ for 3
call i++ for 4
call i++ for 5
call i++ for 6
call + for 6 and 5
call + for 11 and 4
call + for 15 and 3
i++ + i++ + i++ + i++ : 7 18
x 7 xx 12
with the contrast of the results from test case one and two using Int type i defined, i predicted that the test case three should print x 7 xx 18, but it didn't.
my question is how to explain the result?
A sequence point defines any point in a computer program's execution at which it is guaranteed that all side effects of previous evaluations will have been performed, and no side effects from subsequent evaluations have yet been performed. They are often mentioned in reference to C and C++, because the result of some expressions can depend on the order of evaluation of their subexpressions.
Here there are two sequence points at i++(first) and i++(second one). And the Standard says:
" Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression."
So if you try to modify values of a variable between two sequence points, then it will give undefined behavior.
Wiki Link for Sequence Points
http://en.wikipedia.org/wiki/Sequence_point
An expression of the form i++ + i++ will have a compiler-dependent result. The evaluation order is not well defined by the standard, hence, we call this undefined behavior.
Related
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 5 years ago.
Imagine that we have the code below:
int i = 1;
int j = i++ + ++i;
I know that this is a Undefined Behavior, because before the semicolon, which is a sequence point, the value of i has been changed more than once. It means that the compiler may have two possibilities even if the precedence of operator plus is Left-to-Right:
case 1)
take the value of i++ --- value of i is 1
take the value of ++i --- value of i is 2
do the operator plus and assign the result which is 3 to j and do the side effect of i++ (the order of this step is undefined too but we don't care because it won't change the result)
case 2)
take the value of i++ --- value of i is 1
do the side effect of i++ --- value of i is 2
take the value of ++i --- current value of i is 3
do the operator plus and assign the result which is 4 to j
If nothing is wrong here, I have a question:
int j = ++i + i++;
Is the code above still an Undefined Behavior?
In my opinion, there is only one possibility:
do the side effect of ++i --- value of i is 2
take the value of i++ --- value of i is 2
do the operator plus and assign the result which is 4 to j and do the side effect of i++ (the order of this step is undefined too but we don't care because it won't change the result)
Am I right?
Btw I've read this link:
Undefined behavior and sequence points
int j = ++i + i++;
is still undefined behavior since ++i and i++ can be processed simultaneously in multiple pipelines in some CPUs, which will lead to unpredictable results.
No, you are not correct. Each of the expressions ++i and i++ modify i, so the statement modifies i more than once. That is undefined behaviour.
Note that more recent versions of the standards no longer include the concept of "sequence point".
int i = 1;
int j = i++ + ++i;
Evaluation will happen from Right to left, i.e. firstly ++i will be processed then i++. So j will have value 4.
You will get a warning that "operation on 'i' may be undefined" but there is no problem with this expression.
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 3 years ago.
I have switched from MS Visual Studio to gcc, and currently I am trying to recompile some of the codes I have written in VS by gcc. Now I come across something odd. Simply explained, consider the following code, but first, note that I already know it's a very bad code (which is not the point here)
#include <iostream>
int main()
{
int i = 0,
a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
b[10] = { 6, 5, 4, 1, 3, 2, 9, 7, 10, 8 };
while (i ^ 5) a[i++] = a[i] + b[i];
while (i ^ 10) a[i++] = a[i] - b[i];
for (int j = 0; j < 10; j++)
std::cout << a[j] << ' ';
}
When I compile it with Visual Studio, it results in:
7 7 7 5 8 4 -2 1 -1 2
as expected. With gcc v.4.3.6 I also get the same result (Live example).
But when I switch to gcc 5.3.0, it results in:
7 7 5 8 8 -2 1 -1 2 -4198061
after generating many warnings about undefined behavior.
The question is, why visual studio, even in its most recent version, doesn't care about the quality of code and undefined behaviors, and why earlier versions of gcc do the same? What has happened in recent versions of gcc?
This topic is discussed in §1.9/15 (Program execution) of the C++11 standard:
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution
of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. — end note ] 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, and they are not potentially concurrent (1.10), the behavior is undefined. ...
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
}
Undefined Behavior means: anything can happen, the program might behave as you expect or something (as you say) "strange" might happen.
See also: "Sequence point" on Wikipedia:
... depending on the order of expression evaluation, the increment may occur before, after, or interleaved with the assignment. ...
A quick-fix would be to change
while (i ^ 5) a[i++] = a[i] + b[i];
to
while (i ^ 5) a[i] = a[i] + b[i], i++;
This line of code seems to me to be undefined behavior:
a[i++] = a[i] + b[i];
It could means:
a[i] = a[i] + b[i];
i++;
Or :
a[i] = a[i + 1] + b[i + 1];
i++;
It seems the two first compilers use first interpretation while the third compiler uses second interpretation.
'while (i ^ 5) a[i++]' - i modified twice, no sequence point, so UB.
'Between evaluation of the left and right operands of the && (logical AND), || (logical OR) ' - no mention of XOR.
Maybe.......
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
What is the way of working out:
int i=5;
a= ++i + ++i + ++i;
If we go by normal right to left evaluation, the result should be 21 (6 + 7 + 8) .
I remember studying in school, that the answer was 24(8 + 8 + 8)
But I tried it on CodeBlocks, www.ideone.com, ie gcc 4.8.1 compiler and now I get 22.
Could someone please explain the reason
There are no Sequence Points in that expression, so you can't work it out, it is undefined/compiler dependant.
It is as defined by the C/C++ standards an undefined or implementation-defined behavior. The language standards do not specify the behavior, it allows the compiler implementation to choose (and is usually documented).
Also look at another StackOverflow question: Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…).
What GCC does in your example is the following:
int i = 5;
a = ++i + (++i + ++i); // it first gets the value of i and increments it two times
a = ++i + (7 + 7); // it then reads the new value of i, does the addition and save it as a constant in the stack
a = ++i + 14; // it then gets the value of i and increments it
a = 8 + 14; // it then reads the new value of i and add it to the constant
a = 22;
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
order of evaluation of operands
(6 answers)
Closed 9 years ago.
The very amazing and shocking logical problem occur which simple coding in c++.
See the following two chunk of code.
code 1
int m = 5, n = 0;
n = m++ * ++m;
//This print m = 7 and n = 36
//Which is logically wrong
code 2
int m = 5;
int n = m++ * ++m;
//This print m = 7 and n = 35
//Which is logically right
As we think logically the code block 2 gives right answer, but the amazing or magic thing is that what is wrong with code block1?
As part code its same, just we declared int n earlier.
May be some compile!!!!!!
Check http://en.cppreference.com/w/cpp/language/eval_order especially the part which discusses "Undefined behavior". Basically it's not a bug in the compiler. The language says what you're doing is undefined.
Besides the "undefined behavior" part, which is important, there's nothing illogical here. Assuming the evaluation is from right to left:
++m -> value is 6, m is 6
m++ -> value is 6, m is 7
6*6 = 36
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
Why this code is generating 8 as a result ?
#include <iostream>
using namespace std ;
void myFunction(int i)
{
i = i + 2 + ++i;
cout<<i<<endl;
}
void main ()
{
int i = 2;
myFunction(i);
cin>> i;
}
I think the result should be 7 not 8...I am using Visual Studio 2008
The order of evaluation of terms on the right hand side of this expression
i = i + 2 + ++i;
is undefined. i.e. they can occur in any order. In this case the compiler has chosen to increment i first (++i, third term), before evaluating i (first term), which results in 3 + 2 + 3.
You are changing i twice in one statement, and also referencing its value in a way not connected to changing it. This is undefined behavior, and there is no single right answer.
Unspecified behavior. It could be any value. You're not allowed to modify a variable more than once in a single sequence point.
The ++i is executed before all other statements are, so in the line i + 2 + ++i the result is (with i=2) 3 + 2 + 3 which is 8.
It's evaluating "++i" first. "i" is then 3 so you end up with 3 + 2 + 3 = 8.
This is an excellent example of why you should be careful with operators!