4

I was trying to use a pointer to iterate through an object array. Printing values one at a time seems to work fine but it's giving the result in a reversed order when I try to print them all together.

#include<iostream>
using namespace std;

class car{
    int tires;
public:
    car(int a) {tires = a;};
    int GetTires(){return tires;};
};

int main() {
    car array[4] = { 2, 4, 6, 8 };
    car *p;

    p = array;
    cout << ((p++)->GetTires()) << " " << ((p++)->GetTires()) << " " << ((p++)->GetTires())  << " "  << ((p++)->GetTires()) << endl;
   //Prints: 8 6 4 2 

    p = array;
    cout << ((p++)->GetTires()) << " ";
    cout << ((p++)->GetTires()) << " ";
    cout << ((p++)->GetTires()) << " ";
    cout << ((p++)->GetTires()) << " " << endl;
    //Prints: 2 4 6 8

    return 0;
}

Using the C function 'printf' also gives the same output. Can anyone explain why this is happening? TIA.

2 Answers2

8

If you use an older than C++17 compiler, then the order of (p++)->GetTires() evaluations in std::cout::operator << is undefined. Thus your code produces undefined behaviour. Another compiler or your compiler with other compiler settings may produce another output due to another evaluation order.

Between the previous and next sequence point, the prior value of a scalar object that is modified by the evaluation of the expression, must be accessed only to determine the value to be stored. If it is accessed in any other way, the behavior is undefined.

cout << i << i++; // undefined behavior (until C++17)
a[i] = i++; // undefined behavior (until C++17)

Recommend to read: What are the evaluation order guarantees introduced by C++17?

S.M.
  • 13,389
  • 7
  • 29
  • 39
1

Code

cout << ((p++)->GetTires()) << " " << ((p++)->GetTires()) << " " << ((p++)->GetTires())  << " "  << ((p++)->GetTires()) << endl;

does not do same as

    cout << ((p++)->GetTires()) << " ";
    cout << ((p++)->GetTires()) << " ";
    cout << ((p++)->GetTires()) << " ";
    cout << ((p++)->GetTires()) << " " << endl;

This is how typical operator<< looks

ostream& operator<<(ostream& os, const Type& dt)  
{  
    os << dt.value;  
    return os;  
} 

What happens in first line is that compiler would evaluate all sub-expressions that contain increment operator. Order of evaluation isn't defined by standard but and might be not in direction of execution. In result last sub-expression is evaluated first and increment carried over to 3rd third expression and so on.

Swift - Friday Pie
  • 8,633
  • 1
  • 16
  • 31