有人可以澄清当一个整数转换为C中的short
时会发生什么吗?我正在使用Raspberry Pi,所以我知道int
是32位,因此short
必须是16位。
假设我使用以下C代码:
int x = 0x1248642;
short sx = (short)x;
int y = sx;
我认为x
会被截断,但有人可以解释一下究竟是怎么回事?轮班使用了吗?数字究竟是如何从32位截断到16位的?
答案 0 :(得分:38)
根据ISO C标准,当您将整数转换为有符号类型,并且该值超出目标类型的范围时,结果是实现定义的。 (或者可以引发实现定义的信号,但我不知道任何执行此操作的编译器。)
实际上,最常见的行为是丢弃高位。因此,假设int
为32位且short
为16位,则转换值0x1248642
可能会产生类似于0x8642
的位模式。假设有符号类型的二进制补码表示(几乎在所有系统上都使用),高位是符号位,因此结果的数值将为-31166
。 / p>
int y = sx;
这还涉及从short
到int
的隐式转换。由于保证int
的范围至少涵盖short
的整个范围,因此该值不变。 (因为在您的示例中,sx
的值恰好为负值,此表示更改可能涉及符号扩展,将1
符号位传播到所有16结果的高位。)
正如我所说,语言标准不需要这些细节。如果你真的想要将值截断为更窄的类型,那么最好使用无符号类型(具有语言指定的环绕行为)以及可能的显式屏蔽操作,如下所示:
unsigned int x = 0x1248642;
unsigned short sx = x & 0xFFFF;
如果您要将32位数量推送到16位变量中,那么您应该做的第一件事就是决定如果值不合适,您希望代码的行为方式如何。一旦你决定了,你就可以弄清楚如何编写符合你想要的C代码。有时截断恰好是您想要的,在这种情况下,您的任务将很容易,特别是如果您使用的是无符号类型。有时超出范围的值是错误,在这种情况下,您需要检查它并决定如何处理错误。有时您可能希望该值饱和而不是截断,因此您需要编写代码来执行此操作。
了解转化如何在C中发挥作用非常重要,但如果你开始这个问题,你可能会从错误的方向接近你的问题。
答案 1 :(得分:11)
32位值被截断为16位,就像将一个32厘米长的香蕉面包切成16厘米长的平底锅一样。其中一半适合并且仍然是香蕉面包,其余的将是"消失了#34;。
答案 2 :(得分:6)
截断发生在CPU寄存器中。它们有不同的大小:8/16/32/64位。现在,您可以想象一个如下的寄存器:
x
0x1248642
首先获得32位值-----------------------------
| 01 | 24 | 86 | 42 |
-----------------------------
31..24 23..16 15..8 7..0
。在内存*中,它看起来像:
x
现在,编译器在寄存器中加载ax
。从中,它可以简单地加载最低有效16位(即sx
)并将它们存储到 <form>
<div class="input-field">
<p class="range-field">
<input type="range" id="test5" min="0" max="100" />
</p>
</div>
</form>
。
*为简单起见,不考虑字节顺序
答案 3 :(得分:4)
只需从整数中删除高16位。因此,您的空头将变为0x8642
,实际上是负数-31166
。
答案 4 :(得分:4)
或许让代码说明一切:
#include <stdio.h>
#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d"
#define BYTETOBINARY(byte) \
((byte) & 0x80 ? 1 : 0), \
((byte) & 0x40 ? 1 : 0), \
((byte) & 0x20 ? 1 : 0), \
((byte) & 0x10 ? 1 : 0), \
((byte) & 0x08 ? 1 : 0), \
((byte) & 0x04 ? 1 : 0), \
((byte) & 0x02 ? 1 : 0), \
((byte) & 0x01 ? 1 : 0)
int main()
{
int x = 0x1248642;
short sx = (short) x;
int y = sx;
printf("%d\n", x);
printf("%hu\n", sx);
printf("%d\n", y);
printf("x: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
BYTETOBINARY(x>>24), BYTETOBINARY(x>>16), BYTETOBINARY(x>>8), BYTETOBINARY(x));
printf("sx: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
BYTETOBINARY(y>>8), BYTETOBINARY(y));
printf("y: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
BYTETOBINARY(y>>24), BYTETOBINARY(y>>16), BYTETOBINARY(y>>8), BYTETOBINARY(y));
return 0;
}
输出:
19170882
34370
-31166
x: 00000001 00100100 10000110 01000010
sx: 10000110 01000010
y: 11111111 11111111 10000110 01000010
如您所见,int
- &gt;正如预期的那样,short
产生低16位。
将short
转换为int
会产生short
,并设置16个高位。但是,我怀疑这是特定于实现和未定义的行为。你实际上是将16位内存解释为一个整数,它会读出16个额外位的垃圾(如果编译器很好并且希望帮助你更快地发现错误,则读取1个。)
我认为执行以下操作应该是安全的:
int y = 0x0000FFFF & sx;
显然你不会找回丢失的位,但这可以保证高位被正确归零。
如果有人可以验证短 - &gt;使用权威引用的高位行为,这将是值得赞赏的。
注意:二进制宏改编自this answer。
答案 5 :(得分:2)
sx
值与x
的2个最低有效字节相同,在这种情况下,它将是0x8642(如果解释为16位有符号整数),则给出-31166十进制。