当一个int强制转换为短和截断,如何在新的价值决定的?当一个int强制转换为短和截断,如何在新的价值

2019-05-11 21:21发布

有人能澄清当整数转换为个究竟short用C? 我使用树莓裨,所以我知道,一个int是32位,并且因此short必须是16位。

比方说,我用下面的C代码,例如:

int x = 0x1248642;
short sx = (short)x;
int y = sx;

我得到的x将被截断,但有人可以解释究竟如何? 正在使用的变化? 究竟是如何从32位截断为16位的号码?

Answer 1:

根据ISO C标准,当转换的整数有符号类型,并且该值是所述目标类型的范围之外,结果是实现定义的。 (或者实现定义的信号可以提高,但我不知道这样做的任何编译器。)

在实践中,最常见的行为是高阶位被丢弃。 因此,假设int是32位,并且short为16位,转换值0x1248642可能会产生看起来像一个位模式0x8642 。 并假设有符号类型一二进制补码表示(这是在几乎所有系统中使用),则高阶位是符号位,所以结果的数字值将是-31166

int y   =   sx;

这也涉及到的隐式转换,从shortint 。 由于范围int保证以至少覆盖的整个范围short ,则该值是不变的。 (由于在你的例子,值sx恰好是否定的,表示的这种变化可能涉及符号扩展 ,传播所述1符号位的结果的所有16个高位比特)。

正如我指出的,通过语言标准所要求没有这些细节。 如果你真的想截断值更窄的类型,它可能是最好使用无符号类型(其中有语言指定环绕行为),也许明确遮蔽操作,如下所示:

unsigned int x = 0x1248642;
unsigned short sx = x & 0xFFFF;

如果你要推到一个16位变量32位的数量,你应该做的第一件事就是决定如何你想你的代码的行为,如果该值不适合。 一旦你决定,你可以弄清楚如何写C代码,你想要做什么。 有时截断正好是你想要的,在这种情况下,你的任务是一件容易的事,特别是如果你使用的是无符号类型。 有时,超出范围的值是一个错误,在这种情况下,你需要检查一下,再决定如何处理错误。 有时你可能想要的值饱和,而不是截断,所以你需要编写代码来做到这一点。

了解转换用C如何工作是很重要的,但如果你有这个问题你也许会从错误的方向接近你的问题开始



Answer 2:

32位值被截断为16位以同样的方式,如果你果酱它变成一个16厘米长平底锅32厘米长香蕉面包将被削减。 它的一半将融入其中,并且仍然是一个香蕉面包,剩下的将是“水涨船高”。



Answer 3:

截断发生在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


*字节序不考虑为了简单起见



Answer 4:

简单地高16位被从整数切断。 因此,你的短将成为0x8642这实际上是负数-31166



Answer 5:

也许让本身的代码说话:

#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位,符合市场预期。

铸造shortint产生了short与设置的16个高比特。 不过,我怀疑这是实现特定的和未定义的行为。 你基本上解释的内存16位为整数,其内容的任何垃圾恰好有16个额外比特(或1分的,如果编译器是好的,希望帮助您找到的bug更快)。

认为它应该是安全的,请执行以下操作:

int y = 0x0000FFFF & sx;

显然,你不会得到找回了走失的位,但是这将保证高位正确归零。

如果任何人都可以验证短 - 具有权威性参考> INT高比特行为,即,将不胜感激。

注:改编自二进制宏这个答案 。



Answer 6:

sx值将是相同的2个的至少显著字节x ,在这种情况下这将是0x8642哪个(如果解释为16位带符号的整数)给出了在十进制-31166。



文章来源: When an int is cast to a short and truncated, how is the new value determined?