有人能澄清当整数转换为个究竟short
用C? 我使用树莓裨,所以我知道,一个int
是32位,并且因此short
必须是16位。
比方说,我用下面的C代码,例如:
int x = 0x1248642;
short sx = (short)x;
int y = sx;
我得到的x
将被截断,但有人可以解释究竟如何? 正在使用的变化? 究竟是如何从32位截断为16位的号码?
有人能澄清当整数转换为个究竟short
用C? 我使用树莓裨,所以我知道,一个int
是32位,并且因此short
必须是16位。
比方说,我用下面的C代码,例如:
int x = 0x1248642;
short sx = (short)x;
int y = sx;
我得到的x
将被截断,但有人可以解释究竟如何? 正在使用的变化? 究竟是如何从32位截断为16位的号码?
根据ISO C标准,当转换的整数有符号类型,并且该值是所述目标类型的范围之外,结果是实现定义的。 (或者实现定义的信号可以提高,但我不知道这样做的任何编译器。)
在实践中,最常见的行为是高阶位被丢弃。 因此,假设int
是32位,并且short
为16位,转换值0x1248642
可能会产生看起来像一个位模式0x8642
。 并假设有符号类型一二进制补码表示(这是在几乎所有系统中使用),则高阶位是符号位,所以结果的数字值将是-31166
。
int y = sx;
这也涉及到的隐式转换,从short
到int
。 由于范围int
保证以至少覆盖的整个范围short
,则该值是不变的。 (由于在你的例子,值sx
恰好是否定的,表示的这种变化可能涉及符号扩展 ,传播所述1
符号位的结果的所有16个高位比特)。
正如我指出的,通过语言标准所要求没有这些细节。 如果你真的想截断值更窄的类型,它可能是最好使用无符号类型(其中有语言指定环绕行为),也许明确遮蔽操作,如下所示:
unsigned int x = 0x1248642;
unsigned short sx = x & 0xFFFF;
如果你要推到一个16位变量32位的数量,你应该做的第一件事就是决定如何你想你的代码的行为,如果该值不适合。 一旦你决定,你可以弄清楚如何写C代码,你想要做什么。 有时截断正好是你想要的,在这种情况下,你的任务是一件容易的事,特别是如果你使用的是无符号类型。 有时,超出范围的值是一个错误,在这种情况下,你需要检查一下,再决定如何处理错误。 有时你可能想要的值饱和,而不是截断,所以你需要编写代码来做到这一点。
了解转换用C如何工作是很重要的,但如果你有这个问题你也许会从错误的方向接近你的问题开始 。
32位值被截断为16位以同样的方式,如果你果酱它变成一个16厘米长平底锅32厘米长香蕉面包将被削减。 它的一半将融入其中,并且仍然是一个香蕉面包,剩下的将是“水涨船高”。
截断发生在CPU寄存器。 这些具有不同的尺寸:8/16/32/64比特。 现在,你可以想像这样一个寄存器:
<--rax----------------------------------------------------------------> (64-bit)
<--eax----------------------------> (32-bit)
<--ax-----------> (16-bit)
<--ah--> <--al--> (8-bit high & low)
01100011 01100001 01110010 01110010 01111001 00100000 01101111 01101110
x
首先给出32位值0x1248642
。 在内存*,它会是这样的:
-----------------------------
| 01 | 24 | 86 | 42 |
-----------------------------
31..24 23..16 15..8 7..0
现在,编译器载荷x
在寄存器中。 从它,它可以简单地装入至少显著16位(即, ax
)并将它们存储到sx
。
*字节序不考虑为了简单起见
简单地高16位被从整数切断。 因此,你的短将成为0x8642
这实际上是负数-31166
。
也许让本身的代码说话:
#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
- > short
产量低16位,符合市场预期。
铸造short
到int
产生了short
与设置的16个高比特。 不过,我怀疑这是实现特定的和未定义的行为。 你基本上解释的内存16位为整数,其内容的任何垃圾恰好有16个额外比特(或1分的,如果编译器是好的,希望帮助您找到的bug更快)。
我认为它应该是安全的,请执行以下操作:
int y = 0x0000FFFF & sx;
显然,你不会得到找回了走失的位,但是这将保证高位正确归零。
如果任何人都可以验证短 - 具有权威性参考> INT高比特行为,即,将不胜感激。
注:改编自二进制宏这个答案 。
sx
值将是相同的2个的至少显著字节x
,在这种情况下这将是0x8642哪个(如果解释为16位带符号的整数)给出了在十进制-31166。