c - bitwise: different behaviour with negative input value -
i'm on hardware/software interface course hosted on coursera, i'm sure you've seen fair few of these questions..
one of assignments determine whether 2's complement integer x can fit n-bits, using subset of operators, etc. i'm doing well, came across 2 separate approaches, , hit whiteboard them both understand them fully. came confusion.
the function returns 1 if possible fit, 0 if not.
method 1 (correct output)
int foobar(int x, int n) { return !(((x << (32-n)) >> (32-n)) ^x); }
executed positive integer
foobar(5,3) == 0
correctly calculates 5 cannot represented 2's complement 3 bit integer.
executed negative integer
foobar(-4,3) == 1
correctly calculates -4 can represented 2's complement 3 bit integer.
method 1 analysis
x=5, n=3 00000000000000000000000000011101 32 - n == 29 10100000000000000000000000000000 x<<29 00000000000000000000000000000101 >> 29 00000000000000000000000000000101 5 xor 00000000000000000000000000000101 5 -------------------------------- 00000000000000000000000000000000 0 00000000000000000000000000000001 !0 == answer, 1.
as can see, returns 0, in, no 5 may not represented 2's complement integer within 3 bits.
method 2 (incorrect output)
int foobar(int x, int n) { return !((x & ~(1 << (32-n))) ^x); }
executed positive integer
foobar(5,3) == 1
false positive.
executed negative integer
foobar(-4,3) == 0
false negative.
method 2 analysis
x=5, n=3 00000000000000000000000000011101 32 - n == 29 11011111111111111111111111111111 ~(1<<29) , 00000000000000000000000000000101 5 -------------------------------- 00000000000000000000000000000101 5 00000000000000000000000000000101 5 xor 00000000000000000000000000000101 5 -------------------------------- 00000000000000000000000000000000 0 00000000000000000000000000000001 !0 == answer, 1.
i compiling with:
gcc version 4.7.2 (debian 4.7.2-5)
question
i'm @ loss explain difference in output, when analysis shows identical @ bit level, hints/tips can shed light on myself highly appreciated.
thank time!
sc.
in method 1, write
10100000000000000000000000000000 x<<29 00000000000000000000000000000101 >> 29
but not correct (note analysis mean foobar(5,3) == 1
).
first, result of 5 << 29
causes overflow signed 32-bit (or smaller) int
s, undefined behaviour.
next, result, if shift creates indicated bit pattern (as does), negative.
right-shifting negative integers implementation-defined, common arithmetic right shift, sign-extend, , here result in
11111111111111111111111111111101 >> 29
which, when xor-ed 5 gives non-zero result (and applying !
produces 0).
method 2 doesn't work @ all, because, leaving aside undefined behaviour inputs, check whether (32-n)
-th bit set.