tags:

views:

39

answers:

1

Hi everyone. I'm playing with bit shifting. I'm trying to take a 32bit int, save each byte in an array of char, then reconstitute the int. It works the way I think it should, except the second byte from the right seems to have the lowest bit switched. My code is:

int main() {
  char paus[2];
  char b[4] = "abc";
  int c = 6104;
  int d = 0xcccccccc;
  printf("c in hex: %x\n",c);
  printf("d in hex: %x\n",d);
  printf("b[0]: %x\nb[1]: %x\n",b[0]&0xff,b[1]&0xff);
  printf("b[2]: %x\nb[3]: %x/n",b[2]&0xff,b[3]&0xff);
  printf("\n");

  b[0] = c >> 24;
  b[1] = (c >> 16) & 0xff;
  b[2] = (c >> 8) & 0xff;
  b[3] = c & 0xff;
  printf("b[0]: %x\nb[1]: %x\n",b[0]&0xff,b[1]&0xff);
  printf("b[2]: %x\nb[3]: %x\n",b[2]&0xff,b[3]&0xff);
  printf("\n");

  d = (d << 8) + 0x15;
  printf("d in hex: %x\n",d);
  d = (d << 8) + b[1];
  printf("d in hex: %x\n",d);
  d = (d << 8) + b[2];
  printf("d in hex: %x\n",d);
  d = (d << 8) + b[3];
  printf("d in hex: %x\n",d);

  fgets(paus,2,stdin);
  return 0;
}

The output is:

c in hex: 17d8
d in hex: cccccccc
b[0]: 61
b[1]: 62
b[2]: 63
b[3]: 0

b[0]: 0
b[1]: 0
b[2]: 17
b[3]: d8

d in hex: cccccc15
d in hex: cccc1500
d in hex: cc150017
d in hex: 150016d8

Everything makes sense except why the second byte from the right changes to 16 from bit shifting 17 left 8 bits? The 15 and 00 bytes are carried all the way, so why does the 17 byte change? Thanks!

A: 

The problem is that your compiler is set to treat char as signed char. Try this:

d = (d << 8) + (unsigned char)b[3];
printf("d in hex: %x\n",d);

(You would probably want to do the same for the other instances.)

Alternatively, you can change the declaration of d:

unsigned char b[4] = "abc";
Greg Hewgill
ok cool, thanks. That works. But why does it work like that, since only the addition of the last byte changes anything? If I just shift the 17 byte, i get "d in hex: 15001700". It's only after adding the d8 byte it changes. And since the sign bit is the left most, why would it change the right most bit of the preceding byte?
Jade
The underlying reason is that your last byte is the only one that has bit 7 set (ie. its hex value is greater than or equal to 0x80). The high bit is the sign bit, and when it's sign extended to 32 bits (because it's going from an 8 bit signed value to a 32 bit signed value), the value that's actually added is 0xffffffd8.
Greg Hewgill
For more information about representation of negative numbers in two's complement arithmetic, see questions such as http://stackoverflow.com/questions/1125304/why-is-twos-complement-used-to-represent-negative-numbers
Greg Hewgill
got it, thanks guys!
Jade