Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
965 views
in Technique[技术] by (71.8m points)

c - Why does XOR swap with integers trigger a warning?

I typed the following program:

#include <stdio.h>

int main(void) {
    int a = 3;
    int b = 42;

    printf("a = %d
b = %d
", a, b);

    printf("Exchanging values.
");
    a ^= b ^= a ^= b;

    printf("a = %d
b = %d
", a, b);

    return 0;
}

and it's ok. When I try to compile it, I get this:

$ gcc test.c -o test -Wall -Wextra -ansi -pedantic-errors
test.c: In function ‘main’:
test.c:11: warning: operation on ‘a’ may be undefined

That's pretty much standard code, isn't it?

Why does it trigger a warning? As far as I know, bitwise XOR is implemented by default for int as long as you are using a standard implementation of C.

Thank you very much.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Variable a is used as an lvalue twice in the expression.

Keep in mind that x ^= y is in fact a shortcut for x = x ^ y, and it means that the first operand is read, then written.

If you take the first operation out from the original expression, it is fine, see:

   b ^= a ^= b;    // OK
/*    2    1    */

Here, a is used twice and b is used three times. Since the assignment operator is right-to-left associative, first a ^= b is calculated, variable b is only read, variable a is read and then written, and the result (r1) is passed to the second operation. On the second operation, b ^= r1, b is read a second time (giving the same value as read previously) and then written. Note there is no way to interpret differently, no undefined behavior. In the above statement, a is read only once, b is read twice but both reads return the same value, and both a and b is written only once. It is ok.

When you add the third assignment to the left, it becomes a problem:

   a ^= b ^= a ^= b;    // NOT OK
/*    3    2    1    */

Now, a is read twice, once on operation 1 and once on operation 3, and also written on operation 1 and operation 3. What value should a return on operation 3, the original value or the value after operation 1 is processed?

The clever programmer may think that operation 1 is completely executed before operation 3 is processed, but this is not defined by the standard. It just happens to work with most compilers. On operation 3, the compiler may very well return the same value for a as it is returned for operation 1, causing the wrong result. This is undefined behavior.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...