0

I am not able to understand the output of below code . It gives me output as -256.

char c = 0xFF;
printf("%d\n",c<<8);
msc
  • 33,420
  • 29
  • 119
  • 214
SRP
  • 11
  • 1
  • 2
    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – too honest for this site May 22 '17 at 15:01
  • By the way, `(char)0xff` is an odd way to write `(char)-1`. – spectras May 22 '17 at 15:05
  • Did you read the [documentation](https://learn.microsoft.com/nl-nl/cpp/cpp/left-shift-and-right-shift-operators-input-and-output)? – Jeroen Heier May 22 '17 at 15:10
  • 4
    Actually, your whole code is an odd way to calculate (-1) * 256 – tofro May 22 '17 at 15:13
  • @spectras AFAIK, the C standard leaves it explicitly open, whether a platform uses `char` `signed` or `unsigned`. Thus, `(char)-1` is as good or as bad as `(char)0xff`. The system library functions uses often `int` instead of `char` in the respective cases. (For me, this is one possibility to handle a `char` independent of `signed`/`unsigned`.) – Scheff's Cat May 22 '17 at 16:07
  • @Scheff> true (it can even be changed with a compiler flag on most compiler). It was in his specific case, hinting at what was happening. – spectras May 22 '17 at 16:23

2 Answers2

2

First of all, in your platform char is a signed type, which goes from -128 to 127. Following the 2's complement representation, positive numbers are represented from 0x00 to 0x7f and from there, the negative numbers start. So 0x80 is -128, 0x81 is -127, and so on, until arriving to 0xFF which is -1.

In your code, you are assigning -1 to the variable c. When you bitshift a char, it gets promoted to int, so you end up with the representation of -1 in integer, which is (just to give an example) 0xFFFFFFFF if int was 32 bits.

When you bitshift a negative number to the left, the least significant bits get filled by 0's, so you end up having 0xFFFFFF00 which is -256.

lpares12
  • 3,504
  • 4
  • 24
  • 45
  • Incidentally, the same output would be achieved on a silent-wraparound two's-complement implementation where `int` is 16 bits and `char` is any allowable size, – supercat May 22 '17 at 16:27
0

Computers represent negative numbers by using Two's Complement. When you declare a char, you allocate a byte which is 8 bits. If the variable is signed and its most significant bit is 1, it will be the negative value of the 2^n place.

For example, a char which has 8 bits and its sigbit is 1, 0x80 = 1000 0000 = -2^8 = -128. When you set the remaining bits to 1, you add back the positive values of each 2^n bit place. See more about binary representation of numbers here. Each hexadecimal character represent four bits, in the case of 0xFF, you set c's eight bits to 1s.

char c = 0xFF; // 0xFF = 1111 1111 = -1

So you have -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1

When you preform a left-shift c << x, you move c's bits to the left x amount while padding the right with zeros as you shift. Here is a explanation from a previous stackoverflow answer by @legends2k.

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1×2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and non-negative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behaviour is undefined. reference

In addition, when you preform a shift, you promote c to an int.

ISO/IEC 9899:2011 (C)

§6.5.7 Bitwise shift operators

1183 The integer promotions are performed on each of the operands.

To preserve the value of -1 being 0xFF in the sense of a char, on a 32-bit machine, an integer is 4 bytes with its bits all being 1s to represent -1 or 0xFFFFFFFF.

When you shift 8 bits to the left, (0xFFFFFFFF << 8) = 0xFFFFFF00 = -256

Community
  • 1
  • 1
Miket25
  • 1,895
  • 3
  • 15
  • 29