Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If char c = 0x80, why does printf("%d\n", c << 1) output -256?

#include<stdio.h>
int main(void)
{
  char c = 0x80;
  printf("%d\n", c << 1);
  return 0;
}

The output is -256 in this case. If I write c << 0 then the output is -128.

I don't understand the logic behind this code.

like image 1000
Brite Roy Avatar asked Oct 22 '10 23:10

Brite Roy


3 Answers

char may be signed on your platform, in which case 0x80 represents -128 (assuming two's complement).

When a char is used as an operand with the << operator, it is promoted to int (still -128). So when you apply the left-shift, you get -256. Technically, shifting negative values is implementation-defined undefined, but what you see is typical behaviour.

like image 137
Oliver Charlesworth Avatar answered Nov 09 '22 07:11

Oliver Charlesworth


Already your starting point is problematic:

char c = 0x80;

If (as seemingly in your case) char is a signed type, you are assigning the integer constant 128 to a type that is only guaranteed to hold values up to 127. Your compiler then may choose to give you some implementation defined value (-128 in your case I guess) or to issue a range error.

Then you are doing a left shift on that negative value. This gives undefined behavior. In total you have several implementation defined choices plus undefined behavior that determine the outcome:

  • signedness of char
  • the choice of how to convert 128 to signed char
  • the width of char
  • the sign representation of int (there are three possibilities)
  • the choice on how to implement (or not) left shift on negative int

It may be a good exercise for you to look up all these case an to see what the different outcomes may be.

In summary some recommendations:

  • choose an appropriate constant to initialize a variable
  • don't do arithmetic with plain char
  • don't do left shift on signed types
like image 28
Jens Gustedt Avatar answered Nov 09 '22 05:11

Jens Gustedt


c is assigned 0x80. Assuming 8-bit bytes, its value in binary representation, is 10000000. Apparently, on your platform, char is a signed type. So, 0x80 (i.e. 10000000) corresponds to -128.

When << is applied to a char value, it is promoted to int and the sign is preserved. So, when shifted once to the left, with 32-bit integers, it becomes 11111111111111111111111100000000 (two's complement) which is -256.

like image 3
Sinan Ünür Avatar answered Nov 09 '22 05:11

Sinan Ünür