convert int to short in C

牧云@^-^@ 提交于 2019-12-22 04:28:11

问题


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.


回答1:


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.




回答2:


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.




回答3:


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;



回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/18276225/convert-int-to-short-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!