On left shift of (char) 0xff by 8 and casting it to int we get -256 or 0xffffff00. Can somebody explain why this should happen?
#include <stdio.h>
int main (void)
{
char c = 0xff;
printf("%d %x\n", (int)(c<<8),(int)(c<<8));
return 0;
}
Output is
-256 ffffff00
char
can be signed or unsigned - it's implementation-defined. You see these results because char
is signed by default on your compiler.
For the signed char 0xFF corresponds to −1 (that's how two's complement work). When you try to shift it it is first promoted to an int
and then shifted - you effectively get multiplication by 256.
So it is this code:
char c = 0xFF; // -1
int shifted = c << 8; //-256 (-1 * 256)
printf( "%d, %x", shifted, shifted );
When I first looked at the problem, my initial view was that the char 'c' should be shifted left 8 bits - all 8 bits being discarded, the empty char would then be cast to an int of value 0.
A bit of research reveals Usual Unary Conversions - this is where to reduce the large number of arithmetic types, conversions are applied automatically to operands of the unary '!', '-', '~' and '*' operators, and to each of the operands of the binary '<<' and '>>' operators.
Therefore the char 'c' is converted to an int first, then shifted left, giving the answer you see.
You learn something new every day!
c is being promoted to an int before the shift operation is done. Assuming your implementation makes chars signed by default, this means you're going to get 0xffffffff, which is then shifted left to give your result.
If you make c into an unsigned char, you should get what you expect.
char is nothing but signed char. So char c = 0xFF will be -1 . When you left shift -1 by 8 bits you get -256.
来源:https://stackoverflow.com/questions/1097130/in-c-left-shift-char-0xff-by-8-and-cast-it-to-int