1

I'm learning about the C language. I have this code, more can be provided if needed:

int result = 0;
int mask1 = 0x0000ffff;
mask1 = mask1 >> 28;

This when I use gdb and print /x mask1, I get 0x0, which is correct. Then why does:

int result = 0;
int mask1 = 0xffffffff;
mask1 = mask1 >> 28;

print 0xffffffff

shouldn't it be printing 0x0000000f, since I'm left shifting 28 bits?

Does it have to do with the number of bits int takes up on my 64bit machine? I looked at this but it didn't quite answer everything.

Community
  • 1
  • 1
Clara
  • 281
  • 1
  • 3
  • 13
  • 3
    Make `mask1` an `unsigned int` and you will experience the behavior you expect (i.e. logical right shift). – obataku Aug 30 '12 at 22:01
  • Read pragmatic programmer, the book has a section titled "Select is not broken". It describes the problem you've run into here. – Incognito Aug 30 '12 at 22:28

5 Answers5

5

The behaviour of right shifts on negative integers is implementation defined. One common behaviour is arithmetic shifting, which does sign-extension. The advantage of that is that right shifting is then also division by a power of two (rounded to negative infinity), like it is for positive numbers.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
1

You're shifting right. This is right: >>, and this is left: <<.

Commonly, when you shift a (signed) integer right, you're assumed to be changing the value but not the sign: this is what Daniel means by sign extension. It isn't required by the standard and not all platforms do this.

In practise, on a system using twos complement, it means that negative values will have the new top bits filled with 1, and positive values with 0.

Eg, on an 8-bit 2s complement system:

before          after >> 1
11111110 = -2   11111111 = -1 (so new top bit was 1)
00000010 = +2   00000001 = +1 (so new top bit was 0)
Useless
  • 64,155
  • 6
  • 88
  • 132
  • The result of right-shifting a negative integer is implementation-defined. It is not guaranteed to remain negative. – Nemo Aug 30 '12 at 22:08
0

if you print 0xffffffff as an integer, you will realize it is considered as -1.

Bitshift works differently with negative numbers, in that it fills the top most bit with a 1. So basically, 0xffffffff >> 1 == 0xffffffff.

If you declare the mask as unsigned int, then it will probably do what you want.

user711413
  • 761
  • 5
  • 12
0

The bitwise right-shift of a negative integer is implementation-defined.

Here is what gcc does:

The results of some bitwise operations on signed integers (C90 6.3, C99 6.5).

Signed `>>' acts on negative numbers by sign extension.

http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

Community
  • 1
  • 1
ouah
  • 142,963
  • 15
  • 272
  • 331
0

Yes, as @veer pointed out, with int you're doing a Right arithmetic shift which is great for dividing signed numbers by powers of 2 (in two's complement representation):

Right arithmetic shift

By changing the type to unsigned int it will become a Right bitwise shift which is great for dividing unsigned numbers by powers of 2 (which is your scenario):

Right logical shift

Some excellent explanation is on Wikipedia Bitwise operation.

Stephen Quan
  • 21,481
  • 4
  • 88
  • 75