0

I've been experimenting with simple code and I noticed:

short x = 0x8765;
int y = (int)x;
printf("y = %d\n",y);

would print out "y = -30875". I'm wondering why is it the case since when I convert 0x8765 from hex into decimal I got y = 34661.

CSnewbie
  • 103
  • 1
  • 7
  • 2
    Have a look at `printf("x = %d\n",x);`. – dxiv Jul 11 '20 at 05:24
  • Your x is overflowing. As @dxiv said, look at the value of x. – Arpit Bhadauria Jul 11 '20 at 05:25
  • printf("x = %d\n",x); would print out x = -30875 – CSnewbie Jul 11 '20 at 05:27
  • @CSnewbie Right. This hints that you are working with 16-bit `short`, and your hex value represents a negative number. If `int` is also 16-bit then the value is simply copied over, otherwise if it's wider it gets sign-extended. In both cases you end up with a negative number. – dxiv Jul 11 '20 at 05:32

3 Answers3

3

The bit pattern of 0x8765 is negative in a 16-bit signed two's complement integer, but positive in a 32-bit signed two's complement integer.

In an int16_t:

0b1000011101100101
//^ sign bit set

In an int32_t:

0b00000000000000001000011101100101
//^ sign bit unset
Mac O'Brien
  • 2,407
  • 18
  • 22
2

The range of an 4-bytes integer datatype with short type qualifier in C is considered to hold the values from -32,768 to 32,767. But the way you're trying to hold the integer 34661 in the short int is incorrect; the value couldn't be held by it.

Another point, the conversion is clearly correct, since the short int variable x is being overflowed, a negative integer, is then assigned to x and it's explicitly did typecast to int variable y and assigned the value of x in it.

In other words, the maximum value which could be held by short int type in hex: 0x7FFF (i.e. 32767).

Note: You may use unsigned short int to extend the capacity of short from 0 to 65535 (since it's unsigned, the value must not be the negative integer):

|(-32768) + 32767| = -(-32768) + 32767 = 32768 + 32767 => 65535
Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
  • The C language only says the range of short must be *at least* that, not necessarily *exactly* that. – dxiv Jul 11 '20 at 05:28
  • @dxiv Oh, I didn't know. Please link any reference, I'd like to understand about it. – Rohan Bari Jul 11 '20 at 05:29
  • 1
    See the quote and link [here](https://stackoverflow.com/a/37124176). – dxiv Jul 11 '20 at 05:38
  • @dxiv that says in summary that the minimum integer value guarantees to hold -32,768 to 32,767 range in 16-bits machine. It's also compiler-dependent, processor-architecture-dependent (e.g. 16-bits). But here, it seems like the OP has 4 bytes integer, which is converted into 2 bytes due to using the qualifier `short`. – Rohan Bari Jul 11 '20 at 05:42
  • It would work the same if `int` was 16-bit, or 64-bit. You can't tell `sizeof(int)` from OP's question. The `short`, yes, that one has to be exactly 16-bit for this to happen. – dxiv Jul 11 '20 at 05:48
0

If you try to assign the number 0x8765 (34661 decimal) to a short int you are assigning an out of range value to it. The range of short goes from -32768 to +32767 and the literal value in decimal for 0x8765 is +34661 which is clearly over the highest value allowed for a short. So you are incurring on Undefined Behaviour.

What happens is not specified by the standard.

It is the same problem if you try to assign 100000000000 to a char variable. As you have not checked the value in x you thought that the value changed at some point. But it didn't. For some unexplain reason that Undefined Behaviour resulted in -30875 being assigned to x. But also an error could be raised by the runtime, and your program stopped, or even more strange things. That is what U.B. means. Probably if you had printed the values of x and y you could observe the same value on both, demonstrating that the problem came before.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31