2

For a program utilising bitmasks I desired to write numbers in binary... i.e To copy the first 8 bits of x to z, I write

y = 0xff000000;
z = 0;
z = (y & x) | z

Where x, y, z are all int. Now using left shift and right shift operators I wanted to move 1s of y right or left to bitmask another set of bits, so I write the following code

cout<< bitset<32>(y>>10) <<"\n" << bitset<32>(y<<10) <<endl;

Now what I expected as output was:

00000000001111111100000000000000
00000000000000000000000000000000

but I got:

11111111111111111100000000000000
00000000000000000000000000000000
  1. Why are the new bits '1' intead of '0' on first line of output?
  2. How can I change current output to desired output?
edmz
  • 8,220
  • 2
  • 26
  • 45
95_96
  • 341
  • 2
  • 12
  • 6
    use unsigned numbers – user3528438 Feb 20 '16 at 14:12
  • what if i have to use a negative number ? – 95_96 Feb 20 '16 at 14:16
  • Then you need to decide explicitly how you want to handle the negative case. If you require a *logical* shift operation, you'll need to enforce it since your C compiler is likely using *arithmetic* shift for `<<` and `>>` as discussed in [Shift operator in C](http://stackoverflow.com/questions/7622/shift-operator-in-c). You'd replace `y >> 10` with something like `((unsigned)y) >> 10` (or `unsigned long` or whatever unsigned type you need) if you want to retain the sign bit in the shift, as an example. Based upon your treatment of `y`, it's unclear why it's a signed value. – lurker Feb 20 '16 at 14:50
  • Then you shouldn't hack the bits of negative numbers. Hacking bits of negative numbers is as bad/ugly/dangerous/nonportable/UB as hacking the bits of a float. – user3528438 Feb 20 '16 at 15:09

1 Answers1

7

y is a signed integer. In signed integers, the topmost bit is the sign bit, and when you right-shift signed integers the topmost bit propagates.

Using eight-bit values: -4 is

11111100

What do you think makes sense, when you right shift -4?

Do you expect to get -2:

11111110

Or do you expect to get 126?

01111110

Remember that a left shift is an equivalent to multiplying by 2, so a right shift is equivalent to dividing by 2 (and discarding the remainder).

If you want to shift a signed integer, and get unsigned integer semantics, cast it to an unsigned integer, first.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • 1
    The effect of right-shifting a negative value is implementation defined. It's not required to propagate the topmost bit. – Pete Becker Feb 20 '16 at 14:21
  • +1 for the explanation. Per @PeteBecker comment, here's an SO reference discussing it: [Shift operator in C](http://stackoverflow.com/questions/7622/shift-operator-in-c). In this particular case, the OP's tools *happen to use* arithmetic shift. – lurker Feb 20 '16 at 14:46
  • 1
    I'd be curious to know whether any modern platform implements >> on signed values as a logical shift. – Sam Varshavchik Feb 20 '16 at 14:50
  • I agree. The referenced Wikipedia article suggests that it is *usually* implemented as arithmetic. I think it's important to note as a small caveat that it's *possible* a given C compiler may use logical per the standard. – lurker Feb 20 '16 at 14:52