在C中将int转换为short

问题描述 投票:0回答:5

我有:

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

我得到

b = -1
,而我希望
int32
转换为
int16
(
short
)。我希望看到一些价值,但不是
-1

请有人帮我解决这个问题。

c int short
5个回答
27
投票

值 2147483647 或 231-1 溢出 16 位整数。其二进制表示形式的 MSB 为零,其余位为 31。

看起来在您的实现中最后 16 位被转换为

short
。当这种情况发生时,它们全部被设置为
1
,从而产生 -1
2 补码
表示:

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

但是,2-compliment 表示形式和此行为一般都不是 C++ 标准的一部分,因此此行为是实现定义的。


12
投票

将值转换为signed类型时,当源值不适合目标类型时,会产生实现定义结果。这意味着任何符合标准的编译器文档都必须记录结果是什么。

(这与算术运算符溢出时的行为不同。例如:

int overflow = INT_MAX + 1;

实际上有未定义的行为。但无论哪种情况,您都应该小心编写代码,以免引发此类问题。)

对于许多实现,对于转换和算术来说,目标是 N 位类型的溢出只会获取正确结果的 N 低位。

在您的情况下,显然

int
是 32 位,而
short
是 16 位(这些大小可能因不同的实现而异)。
2147483647
0x7fffffff
,低 16 位是
0xffff
,(同样,在您的实现中)
-1
在类型
short
中的表示。

对于无符号类型的转换,结果是由标准严格定义的;它采用结果的低位 N 位。对于溢出浮点转换(例如,将非常大的

double
值转换为
float
),行为是未定义的。

到目前为止,这对于 C 和 C++ 来说都是一样的。但更令人困惑的是,从 1999 年标准开始,允许溢出有符号转换来引发实现定义的信号。 C++没有这个。我不知道有哪个编译器真正做到了这一点。

我希望看到一些价值,但没有

-1

-1
“一些价值”。您期望有一些具体的价值吗?

顺便说一下:

short b = (short)a;

演员阵容是不必要的。赋值、初始化、参数传递和

return
语句可以在任何数字类型之间赋值,而无需强制转换。该值被隐式转换:

short b = a;

9
投票

你的int A 比short 的大小大。当您将 A 转换为 Short 时,最左边的位会得到 1,这表明它是一个负数。既然你得到了 -1,我想你在所有 16 位中都得到了 1,这会给你 -2^15 + 2^14 + 2^13... + 2^0,这会给你-1。简而言之(没有双关语),如果整数太大,则无法将整数转换为短整型。


9
投票

这是

implementation defined
行为,例如
gcc
Integers Implementation document
说:

为了转换为宽度为 N 的类型,该值会 模 2^N 减少到该类型的范围 内;没有发出任何信号。

这可能因编译器而异,我无法为

clang
visual studio
找到类似的文档。

来自 C++ 标准草案,第

4.7 Integral conversions
段落
3

如果目标类型有符号,并且可以用目标类型(和位字段宽度)表示,则该值保持不变;否则,该值是实现定义的

如果这是

unsigned
,那么你将拥有完全明确的行为,如段落
2

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2n,其中 n 是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。 ——尾注]

C99
标准草案部分
6.3.1.3 Signed and unsigned integers
中的语言类似。


4
投票

你可以这样做:

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

校验和为

0x1234

还有另一种方法:

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

输出为

1234

© www.soinside.com 2019 - 2024. All rights reserved.