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 i.e. 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 (i.e. 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;
}