Reputation: 958
I found something weird, I tested this code:
#include <iostream>
using namespace std;
int main() {
int i=0, a[5];
cin>>a[i++]>>a[i++]>>a[i++];
for(int j=0; j<i; j++){
cout<<a[j]<<endl;
}
}
With this input:
1
2
3
And got the input reversed like this:
3
2
1
I thought its output should be the same as this code:
#include <iostream>
using namespace std;
int main() {
int i=0, a[5];
cin>>a[i++]; cin>>a[i++]; cin>>a[i++];
for(int j=0; j<i; j++){
cout<<a[j]<<endl;
}
}
Anybody had experienced this before? Thanks.
-Edit-
Thanks all for the answers!!!
Upvotes: 5
Views: 293
Reputation: 263220
cin>>a[i++]>>a[i++]>>a[i++];
is just syntactic sugar for
cin.operator>>(a[i++]).operator>>(a[i++]).operator>>(a[i++]);
Now, the three calls to operator>>
are definitely executed from left to right, but the three arguments a[i++]
can be evaluated in any order. Let's call the arguments x
, y
and z
:
cin.operator>>(x).operator>>(y).operator>>(z);
You might expect the compiler to substitute x
, y
and z
as follows:
int& x = a[i];
i++;
int& y = a[i];
i++;
int& z = a[i];
i++;
But in fact, the compiler is give much more freedom. In your case, it chose:
int& z = a[i];
i++;
int& y = a[i];
i++;
int& x = a[i];
i++;
And as James Kanze points out, it could also have chosen:
int& x = a[i];
int& y = a[i];
int& z = a[i];
i++;
i++;
i++;
Upvotes: 5
Reputation: 311048
As already was said the code has undefined behaviour because the order of evaluation of function arguments are not specified and as the result applying of the side effects of postincrement operators are not sequenced in the deterministic way.
Howevrr I will explain the result.
Expression
cin>>a[i++]>>a[i++]>>a[i++];
is equivalent to the followiung expression if we will use functional notation
cin.operator >>( a[i++] ).operator >>( a[i++] ).operator >>( a[i++] );
The order of evaluation of function arguments are not specified. So some compilers evaluate arguments right to left while others - left to right.
It is obvious that your compiler evaluates function arguments right to left. The first is evaluated the argument of the right most function
cin.operator >>( a[i++] ).operator >>( a[i++] ).operator >>( a[0] );
After evaluation of the argument the compiler applies the side effect. i becomes equal to 1. Then the compiler evaluares the argument of the second function and you get
cin.operator >>( a[i++] ).operator >>( a[1] ).operator >>( a[0] );
And at last after evaluation the argument of the first function call there will be
cin.operator >>( a[2] ).operator >>( a[1] ).operator >>( a[0] );
and variable i will be equal to 3.
However as the order of evaluation of function arguments as I said are nor specified other compilers can represent this expression as
cin.operator >>( a[0] ).operator >>( a[1] ).operator >>( a[2] );
So the result can be different and the behaviour of the program is undefined.
Upvotes: 1
Reputation: 361
When you modify and use variable inside the same statement, That results in Undefined behaviour. i is modified 3 times and accessed 3 times in statement below.
cin>>a[i++]>>a[i++]>>a[i++];
I guess below code will work fine.
#include <iostream>
using namespace std;
int main() {
int i=0, a[5];
cin>>a[0]>>a[1]>>a[2];
i=3;
for(int j=0; j<i; j++){
cout<<a[j]<<endl;
}
}
Upvotes: 2
Reputation: 234785
The behaviour of the statement cin>>a[i++]>>a[i++]>>a[i++];
is actually undefined. This is because there are no sequence points.
You don't know when i
will be incremented and your output is therefore not surprising.
See http://en.wikipedia.org/wiki/Sequence_point
Upvotes: 8
Reputation: 35438
This feels like undefined behaviour and compiler dependent:
cin>>a[i++]>>a[i++]>>a[i++];
(masters, please correct me if I'm wrong)
Upvotes: 8