Neoqq
Neoqq

Reputation: 958

C++ - Weird thing, input got reversed

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

Answers (5)

fredoverflow
fredoverflow

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

Vlad from Moscow
Vlad from Moscow

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

Singh
Singh

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

Bathsheba
Bathsheba

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

Ferenc Deak
Ferenc Deak

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

Related Questions