1

I am trying to set the least significant bit to all bit places. For instance, copyLSB(6) would yield 0x00000000 whereas copyLSB(5) would yield 0xffffffff.

Here is my code:

int copyLSB(int x) {
  int r = x << 31;
  r = x >> 31;
  return r;
}

The program works for 6 and 5. However, when I input 0x80000000 it fails and returns 0xffffffff.

Hi guys, I found a way to do this without using bit shifting and this works on signed numbers too.

int copyLSB(int x) {                                                                                                   │
        int result = x & 1;                                                                                            │
        return ~(~(x & 0) + result);                                                                                   │
}
mrQWERTY
  • 4,039
  • 13
  • 43
  • 91
  • 3
    Please don't do bit arithmetic on signed values. Please. – Lightness Races in Orbit Sep 20 '14 at 21:19
  • @LightnessRacesinOrbit Thats part of my assignment haha. – mrQWERTY Sep 20 '14 at 21:20
  • 1
    Then your assignment is teaching you practices that would get you fired from my team. – Lightness Races in Orbit Sep 20 '14 at 21:20
  • @LightnessRacesinOrbit When do we actually use bitwise operators then? – mrQWERTY Sep 20 '14 at 21:23
  • 3
    @Renren29: With unsigned values. – Bill Lynch Sep 20 '14 at 21:23
  • go with an unsigned long rather than an int. results of shifting depends on how the underlying hardware registers do shifting. with signed values the likelihood of sign extension is very high so that if the high order bit is set and you do a right shift, the hardware will tend to keep the high order bit set. See http://stackoverflow.com/questions/4009885/arithmetic-bit-shift-on-a-signed-integer – Richard Chambers Sep 20 '14 at 21:23
  • Also see this stack overflow which discusses some of the hardware differences depending on the CPU and instruction set. [why right shifting negative numbers in c brings 1 on the left most bits](http://stackoverflow.com/questions/17358445/why-right-shifting-negative-numbers-in-c-brings-1-on-the-left-most-bits) – Richard Chambers Sep 20 '14 at 21:30
  • Assuming your system has 32-bit `int`s, an `int` *cannot* hold the value `0x80000000` or `0xffffffff`. The maximum value a 32-bit `int` can hold is `0x7fffffff`, or 2147483647 (2**31-1). You haven't shown us how you're displaying the values; presumably you're doing something that assumes values of type `unsigned int` rather than `int`. – Keith Thompson Sep 20 '14 at 21:38
  • `0x80000000` is `-2147483648`, `0xffffffff` is `-1`. BTW, you could implement copyLSB without shifts, but the question is why shifts not work. – alexander Sep 20 '14 at 21:45
  • @alexander: No, `0x80000000` is not `-2147483648`, it's `+2147483648`. They might happen to have the same representation *in different types*, but they're distinct values. C operators are defined in terms of values, not representations. – Keith Thompson Sep 20 '14 at 22:11

1 Answers1

3

0x80000000 is a negative number, if your ints are 32-bit and two's complement is used.

Left shift of negatives is undefined behavior. Right shift of negatives is implementation defined behavior.

From the standard:

6.5.7 Bitwise shift operators

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. .... If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

....

The result of E1 >> E2 is E1 right-shifted E2 bit positions. ... If E1 has a signed type and a negative value, the resulting value is implementation-defined.

AlexD
  • 32,156
  • 3
  • 71
  • 65