Bizarre right bitshift inconsistency

1

I've been working with bits in C (running on ubuntu). In using two different ways to right shift an integer, I got oddly different outputs:

#include <stdio.h>
int main(){
int x = 0xfffffffe;
int a = x >> 16;
int b = 0xfffffffe >> 16;
printf("%X\n%X\n", a, b);
return 0;
}

I would think the output would be the same for each: FFFF, because the right four hex places (16 bits) are being rightshifted away. Instead, the output is:

FFFFFFFF
FFFF

What explains this behaviour?

c
ubuntu
bit-manipulation
bit-shift
asked on Stack Overflow Sep 21, 2018 by 16jacobj • edited Mar 25, 2019 by tadman

2 Answers

4

When you say:

int x = 0xfffffffe;

That sets x to -2 because the maximum value an int can hold here is 0x7FFFFFFF and it wraps around during conversion. When you bit-shift the negative number it gets weird.

If you change those values to unsigned int it all works out.

#include <stdio.h>
int main(){
  unsigned int x = 0xfffffffe;
  unsigned int a = x >> 16;
  unsigned int b = 0xfffffffe >> 16;
  printf("%X\n%X\n", a, b);
  return 0;
}
answered on Stack Overflow Sep 21, 2018 by tadman
2

The behaviour you see here has to do with shifting on signed or unsigned integers which give different results. Shifts on unsigned integers are logical. On the contrary, shift on signed integers are arithmetic. EDIT: In C, it's implementation defined but generally the case.

Consequently,

int x = 0xfffffffe;
int a = x >> 16;

this part performs an arithmetic shift because x is signed. And because x is actually negative (-2 in two's complement), x is sign extended, so '1's are appended which results in 0xFFFFFFFF.

On the contrary,

int b = 0xfffffffe >> 16;

0xfffffffe is a litteral interpreted as an unsigned integer. Therefore a logical shift of 16 results in 0x0000FFFF as expected.

answered on Stack Overflow Sep 21, 2018 by Sydney Hauke • edited Sep 21, 2018 by Sydney Hauke

User contributions licensed under CC BY-SA 3.0