Incrementing pointer in conditional statement

Hi all!

I got this little program to work eventually (see second code excerpt), but I was a little surprised the first version didn't work at all, and I would really like to understand why :) Could you help me?

Original version (doesn't work as expected)

1
2
3
4
5
6
7
8
9
10
bool  a[4] = {true,false,true,true};
bool* b    = a;

for (int i=1; i<4; i++)
    if ( (*(b++))^(*b) )
        cout << "Xor at " << i << endl;

// Expected output:
// Xor at 1
// Xor at 2 


Working loop:

1
2
3
for (int i=1; i<4; i++, b++)
    if ( (*b)^(*(b+1)) )
        cout << "Xor at " << i << endl;


Thanks, J
You can't modify a variable and read from it in the same sequence point.

IE:

1
2
int i = 0;
int foo = (i++) + i;  // might be 0, might be 1, exact output is undefined 


The reason for this is because the compiler is free to actually increment 'i' whenever it decides is best.


Your original code is similar:

if ( (*(b++))^(*b) )

Are you expecting the first "b++" to change b before you do "*b"?
Whether or not that actually happens is undefined.
Thanks a lot Disch! That's exactly what I expected, and I understand your answer. Indeed, it makes sense to give that liberty to the compiler, but wouldn't it be as simple for 'it' to increment it at the end of the instruction?

I'm just pushing for more details if you know them, but that's purely out of curiosity, you answered my first question!
That doesn't seem right. If you aren't allowed to modify a variable while reading from it, why do we have both prefix and postfix increment and decrement? Wouldn't this rule prevent you from using the return value anyway?
Hi Telion,

Thanks for your answer!
I reopened the problem because I think there's something deeper I don't understand, unless Disch is right and the order in which the pointer is incremented is totally undefined.

Here is a little example that I can't explain at all:

1
2
3
4
5
6
7
int  b[3] = { 1,2,3 };
int* a    = b;
cout << *a << endl;
cout << *(a++) << " " << *a << " " << *(--a) << endl;
cout << *(a++) << " " << *a << endl;
a++;
cout << *(a++) << " " << *a << " " << *(--a) << endl;


And here is the output:

1
2
3
4
1
-858993460 1 1
1 2
2 3 3


I think I'm just going to stop playing with pointer incrementation...
@ telion: all write operators also do a read. The point I meant to say was that you can't do an additional read with that write.

Terminux's latest example illustrates this beautifully:

1
2
3
int  b[3] = { 1,2,3 };
int* a    = b;
cout << *(a++) << " " << *a << " " << *(--a) << endl;

-858993460 1 1


This output is perfectly legal. Here's what the compiler is doing:

1
2
3
4
5
6
--a;  // pre-decrementing (decrement before the --a is printed)
cout << a;  // the "a++" print, printing before "a++" is incremented
   // prints b[-1] (garbage)
a++;  // post-incrementing a (perform the a++ incrementing)
cout << a;  // the "*a" print, printing b[0] (1)
cout << a;  // the "--a" print, printing b[0] (1) 


Notice that even though the output is not what you might have expected, the compiler legally obeyed all operator precedence rules. That is:

1) "--a" decremented a before it was read (decremented on line 1, read on line 6)
2) "a++" incremented a after it was read (read on line 2, incremented on line 4)
3) -- and ++ were both evaluated before their respective << operator


The language rules say nothing about whether --a or a++ have to be evaluated first. Therefore the behavior is undefined.

You should never, ever do this in any program.
Last edited on
Thanks again Disch, your explanation was really clear :)

The fact that the sequence of execution is difficult to predict, added to the fact that this kind of code is actually difficult to (re)read, make these forms practically unusable in a real program, so I'll stop playing with that.
Topic archived. No new replies allowed.