convert int to short in C

2020-08-25 05:25发布

I have:

int a = 2147483647;
short b = (short)a;

and I get b = -1 whereas I expect int32 to be converted to int16(short). I expect to see some value and not -1.

Please someone help me with this.

标签: c int short
5条回答
迷人小祖宗
2楼-- · 2020-08-25 05:48

You can do this:

uint32_t sum=0xFFFF1234;
uint16_t *p= (uint16_t *) ∑
uint16_t checksum=p[0]; 

check-sum is 0x1234.

Here is another way:

union ToShort
{
        uint32_t sum;
        uint16_t checksum[2];
} toShort;
toShort.sum=0xFFFF1234;
cout << hex << toShort.checksum[0];

output is 1234.

查看更多
狗以群分
3楼-- · 2020-08-25 05:53

Converting a value to a signed type, when the source value doesn't fit in the target type, yield an implementation-defined result. That means that any conforming compiler's documentation must document what that result is.

(This is unlike the behavior on overflow of an arithmetic operator. For example:

int overflow = INT_MAX + 1;

actually has undefined behavior. But in either case, you should be careful to write your code so it doesn't trigger this kind of problem.)

For many implementations, for both conversion and arithmetic, an overflow where the target is an N-bit type simply takes the N low-order bits of the correct result.

In your case, apparently int is 32 bits and short is 16 bits (those sizes can vary on different implementations). 2147483647 is 0x7fffffff, the low-order 16 bits are 0xffff, which is (again, on your implementation) the representation of -1 in type short.

For conversion to unsigned types, the result is strictly defined by the standard; it takes the low-order N bits of the result. And for overflowing floating-point conversion (say, converting a very large double value to float), the behavior is undefined.

So far, this is all the same for C and C++. But just to add to the confusion, starting with the 1999 standard an overflowing signed conversion is permitted to raise an implementation-defined signal. C++ doesn't have this. I don't know of any compiler that actually does this.

I expect to see some value and not -1.

-1 is "some value". Was there some specific value you expected?

Incidentally:

short b = (short)a;

The cast is unnecessary. Assignment, initialization, parameter passing, and return statements can assign values between any numeric types without a cast. The value is converted implicitly:

short b = a;
查看更多
We Are One
4楼-- · 2020-08-25 05:57

Your int A is larger than the size of short. When you convert A to short, you get a 1 in the left most bit, which is going to indicate that it is a negative number. Since you're getting -1, I suppose you're getting 1s in all 16 bits, which is going to give you -2^15 + 2^14 + 2^13... + 2^0, which will give you -1. In short (no pun intended), you can't convert the integer to a short if it is too large.

查看更多
兄弟一词,经得起流年.
5楼-- · 2020-08-25 06:06

The value 2147483647, or 231-1 overflows a 16-bit integer. Its binary representation is zero in the MSB followed by 31 ones in the remaining bits.

It looks like in your implementation the last 16 bits are taken in the conversion to short. When this happens, all of them are set to 1, resulting in a 2's complement representation of -1:

32-bit int:   01111111111111111111111111111111
16-bit short: ----------------1111111111111111

However, neither the 2-compliment representation nor this behavior in general is part of the C++ standard, so this behavior is implementation-defined.

查看更多
家丑人穷心不美
6楼-- · 2020-08-25 06:12

This is implementation defined behavior, for example gcc Integers Implementation document says:

For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type; no signal is raised.

This can differ from compiler to compiler, I am not able to dig up similar documents for clang nor visual studio.

From the draft C++ standard, section 4.7 Integral conversions paragraph 3:

If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.

If this was unsigned then you would have perfectly well defined behavior, as per paragraph 2:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

The language is similar in the C99 draft standard section 6.3.1.3 Signed and unsigned integers.

查看更多
登录 后发表回答