简体   繁体   中英

#define FUNC(x,y) x=^y; y^x; in c

Im having trubles to understand what it means when there is define and then two xor expressions. what this define does?

i try to send x=8, y=7 and the result was that x=15 and y=8 why its happand?

this is the program:

#define FUNC(a,b) a^=b; b ^=a;

int main(){
    int x=8,y= 7;
    FUNC(x,y);
    printf("%d %d\n",x, y);
}

It is just the same as

int main(){
    int x=8,y= 7;
    x^=y; y ^=x;;
    printf("%d %d\n",x, y);
}

because the define will just be a simple text substitution, ie all places with a will be replaced by x and all places with b will be replaced with y .

The ^ is a bit wise XOR operator.

So first x = 8 ^ 7 = 15 then y = 7 ^ 15 = 8

This is because XOR produce 1 when one of the bits are 1 都是1

x =  8 = 0b00000000000000000000000000001000  // Assuming 32 bit int
y =  7 = 0b00000000000000000000000000000111  // Assuming 32 bit int
 x=x^y = 0b00000000000000000000000000001111 = 15

x = 15 = 0b00000000000000000000000000001111  // Assuming 32 bit int
y =  7 = 0b00000000000000000000000000000111  // Assuming 32 bit int
 y=y^x = 0b00000000000000000000000000001000 = 8
                                        ^^^
                                        Zero because both bits are 1

More to the original question:

This macro has the first two steps of the bit-wise method to exchange two values:

(1) a ^= b
(2) b ^= a
(3) a ^= b

Let's expand this a little: let x = a; y = b, and we'll trace the algebra through terms of x and y. First, replace each "update" with its full expression:

(1) a = a ^ b
(2) b = b ^ a
(3) a = a ^ b

Now, substitute x and y, trickling down from top to bottom:

(1) a = x ^ y
(2) b = y ^ (x ^ y)
(3) a = (x ^ y) ^ (y ^ (x ^ y))

Drop the parentheses and rearrange terms:

(1) a = x ^ y
(2) b = x ^ y ^ y
(3) a = x ^ x ^ y ^ y ^ y

... leaving us with b = x; a = y

Now, since you have only the first two steps, your final result is

b = x (original value of a)
a = x ^ y (a.k.a. a ^ b)

Does that explain the immediate problem for you?

The canonical way to #define multi-statement macros is

#define FUNC() do { statement1; statement2; } while(0)

That way even if(b) FUNC(); does what the caller thinks.

There has been a discussion a few years ago which led to a change in the MISRA rules concerning this; MISRA does not recommend the "do" strategy any longer, because they say one should always use curly braces, as in if(b) { FUNC(); } if(b) { FUNC(); } which would handle unprotected multi-statement macros gracefully (and prevent bugs like the Apple certificate goto screw-up). Instead, a do{... would camouflage the failure to use braces.

I think I personally still side on the do side, if only because I know it.

CERT recommends the technique as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM