1

I am reading about shift operators in C.

Right shifting n bits divides by 2 raise to n. Shifting signed values may fail because for negative values the result never gets past -1: -5 >> 3 is -1 and not 0 like -5/8.

My question is why shifting signed values may fail?

Why value of -5 >> 3 is -1 and not zero?

Kindly explain.

Mat
  • 202,337
  • 40
  • 393
  • 406
venkysmarty
  • 11,099
  • 25
  • 101
  • 184
  • Because right shift duplicates the sign bit. If you start with negative number, you will end with negative number (all ones in binary, which is -1 in 2's complement). – oakad Apr 29 '14 at 06:04
  • @oakad for example -5 is represented as 1000 0101 for one byte. If we do right shift for we ge 1111 0000. How we get -1? – venkysmarty Apr 29 '14 at 06:08
  • @venkysmarty -5 in 8 bits is 11111011. Shift right by 3 will give you 11111111. http://en.wikipedia.org/wiki/Two%27s_complement – oakad Apr 29 '14 at 06:09
  • 8
    A bit of unsolicited advice: Only use bit shifting when you actually care about patterns of bits. When you care about the value of the variable as an actual integer, then use arithmetic operations. Also, when you do use bit shifting, only do it on unsigned types. It's implementation dependent what happens if you bit shift a negative integer. – Corbin Apr 29 '14 at 06:09
  • @Corbin: a *negative* signed integer. Bit shifting of positive signed integers is well defined as far as you stay in their range. (just nitpicking, +1 for the rest) – Matteo Italia Apr 29 '14 at 06:12
  • 1
    @oakad: the behaviour of right shift on signed quantities is not guaranteed to be a arithmetic shift (shifting in the same bit as the most significant bit) or a logical shift (shifting in zeros); both are permissible according to the standard. – Jonathan Leffler Apr 29 '14 at 06:12
  • @MatteoItalia Whoops, thought it was undefined in general for signed types. Thanks! – Corbin Apr 29 '14 at 06:14
  • @Jonathan Leffler Op was asking why he's getting the value he's getting. The standard, on the other hand, has to consider odd Univacs still hanging around, which may behave differently. :) – oakad Apr 29 '14 at 06:16

2 Answers2

0

It is simply implementation-defined:

From 5.8 Shift operators

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand

[...]

If E1 has a signed type and a negative value, the resulting value is implementation-defined.

  • You seem to have mixed up left and right. The relevant quote is "If E1 has a signed type and a negative value, the resulting value is implementation-defined" (not undefined). – Mike Seymour Apr 29 '14 at 06:21
-1

Shifting with signed integers is implementation defined, but if the architecture you're using has an arithmetic shift, you can pretty reliably guess it with use it.

It's because of how negative numbers are stored in the computer. It's called two's complement. To switch the sign of a two's complement, you NOT its bits and add 1. For example, with an 8 bit integer 00011010 (26), first you NOT to get 11100101, then you add 1 and get 11100110 (-26). The problem comes from that most significant bit being set. If when you shifted it put 0s in at the left, the number would become positive, but if it put 1s, then the lowest possible result is 11111111 which is -1. This is how arithmetic shifts work, when you shift the computer adds bits that are the same as the left most bit.

So to be explicit, this is what is happening (using 8 bit integers because it's easier and the size is arbitrary in this case): 11111011 gets shifted 3 to the right (so 011 goes away) and since the most significant bit is set 3 1s are inserted at the top, so you get 11111111 which is -1.

Tyler
  • 1,818
  • 2
  • 13
  • 22