简体   繁体   中英

Bit Operations - Indicating the Sign of a Signed Integer

Why does the following C code not work for returning -1 for negative numbers, 0 for 0s, and 1 for positive numbers?

(((x >> 31) ^ -1) + 1) | (!x ^ 1);

Specifically, when I pass in negative numbers, it returns 1. It seems like if I have a negative number, though (ie, the the least significant bit is a 1 after the 31 bit shift), XORing it with -1 will give me -2 (ie, all 1s and a 0 in the least significant bit location), and adding 1 would make it -1.

>> will generally do arithmetic shift on signed data, so ((-1) >> 31) == (-1) , contrary to your assumption. As pointed out by others, this is not guaranteed by the standard, but it is most likely true on modern systems. In any case, be careful with this type of bit twiddling. If portability is a concern or speed is not, you should do it a different way. See Is there a standard sign function (signum, sgn) in C/C++? for some ideas.

According to the C99 standard, the result of x >> n if x is negative is implementation defined. So the reason you are having a problem depends on your compiler and architecture.

However, it's most likely that the x is sign extended when you shift it ie the top bit is repeated to keep the sign the same as the operand. This is what happens with my compiler. So for any negative number, x >> 31 is -1 . Also, for any non zero number !x is 0 (ie false). This applies assuming x is a 32 bit integer. If you make x an unsigned int, it should work, but consider the following alternative:

(x < 0) ? -1 : ((x > 0) ? 1 : 0)

which I think is a bit less cryptic.

And here is a program that you can use to see what your expression is doing

#include <stdio.h>
#define EVALUATE(x)     printf("%s = %d\n", #x, x)
int main(int argc, char** argv)
{
    unsigned        int x = 51;

    EVALUATE(x >> 31);
    EVALUATE(((x >> 31) ^ -1));
    EVALUATE(((x >> 31) ^ -1) + 1);
    EVALUATE(!x);
    EVALUATE(!x ^ 1);
    EVALUATE((((x >> 31) ^ -1) + 1) | (!x ^ 1));
    return 0;
}

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