0

I learned using Xor operator to swap two integers,like:
int a = 21;
int b = 7;
a^=b^=a^=b;

I would finally get a=7 and b=21.

I try to use xor operator on array like this way:

int main()
{
    int a[] = {7,21};  
    a[0]^=a[1]^=a[0]^=a[1];

    cout << a[0] <<',' <<a[1];
    return 0;
}

The output is 0,7
I compile the code on Xcode and g++, they have the same issue.

Xor swap on array works fine with multiple lines:

int main()
{
    int a[] = {7,21};  
    a[0]^=a[1];
    a[1]^=a[0];
    a[0]^=a[1];
    cout << a[0] <<',' <<a[1];
    return 0;
}

I would get output as 21,7

Here is the information what I already find:
- the issue is about sequence point: Array + XOR swap fails
- even for simple integers, they may have side affect to this undefined behavior: Why is this statement not working in java x ^= y ^= x ^= y;
- some other issue on xor swap: Weird XOR swap behavior while zeroing out data

So I should avoid using xor swap, instead, swap with temp would guarantee correct result.

But I still not very clear about what happen on a[0]^=a[1]^=a[0]^=a[1]; what is the sequence point issue with it?

I could not figure out what's the different on compiler between a[0]^=a[1]^=a[0]^=a[1]; and a^=b^=a^=b; ?


My doubt is:
" How does compiler output 0,7 for a[0]^=a[1]^=a[0]^=a[1];. "

I know this is sequence pointer issue, I could understand why printf("%d,%d",i++, i++); is undefined as some compiler parse parameter of function from left to right, and some do it from right to left.

But I do not know what is the problem on a[0]^=a[1]^=a[0]^=a[1];, it looks just the same as a^=b^=a^=b;. So I'd like to know how it works with array. So that I would know more about kind like "sequence pointer on index of array"

Community
  • 1
  • 1
Ider
  • 11
  • 4

1 Answers1

8

You cannot modify a variable more than once without an intervening sequence point, if you do so, it is Undefined Behavior.

a^=b^=a^=b;

Trying to modify the values of a and b in the above statement breaks this rule and you end up with an Undefined Behavior.
Note that Undefined Behavior means that any behavior is possible and you can get any output.

Good Reads:

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Meaning, you should be all right if you add parentheses as appropriate, or stick to separate statements separated by ; – DRVic Mar 31 '12 at 18:54
  • 2
    @DRVic: Parentheses won't help. – Oliver Charlesworth Mar 31 '12 at 19:03
  • Really? a ^= ( b ^= ( a ^= b ) ) requires that a ^= b is first evaluated before the result is used in b ^= (a^=b) which must be evaluated before the result is used in a ^= ( b ^= ( a ^= b ) ). – DRVic Mar 31 '12 at 19:10
  • 3
    @DRVic: Nope, not in C and C++. Only at a sequence point you can be sure which side effects have taken place and which haven't. See http://stackoverflow.com/q/4176328/395760 –  Mar 31 '12 at 19:28
  • @DRVic: [Here](http://www.viva64.com/en/t/0065/) is a list of Sequence points in C++. – Alok Save Mar 31 '12 at 19:31
  • Note that this is no longer UB as of C++11. – Baum mit Augen Jul 17 '16 at 14:40