我想转换 65529 从一个 unsigned int 要签名的 int.我试着做一个铸造这样的:

unsigned int x = 65529;
int y = (int) x;

y 仍然是返回65529时,它应该回-7.为什么?

有帮助吗?

解决方案

好像您期待 intunsigned int 成为16位整数。显然不是这样。最有可能是一个32位整数 - 足够大,可以避免您期望的包裹。

请注意,没有完全符合C的方式来执行此操作,因为在范围内为符号的签名/未签名之间的铸造是实现定义的。但这在大多数情况下仍然有效:

unsigned int x = 65529;
int y = (short) x;      //  If short is a 16-bit integer.

或或者:

unsigned int x = 65529;
int y = (int16_t) x;    //  This is defined in <stdint.h>

其他提示

我知道这是一个古老的问题,但这是一个很好的问题,那呢?

unsigned short int x = 65529U;
short int y = *(short int*)&x;

printf("%d\n", y);

@Mysticial得到了它。一个简短的通常是16位与会说明的答案:

int main()  
{
    unsigned int x = 65529;
    int y = (int) x;
    printf("%d\n", y);

    unsigned short z = 65529;
    short zz = (short)z;
    printf("%d\n", zz);
}

65529
-7
Press any key to continue . . .


一个小小的更详细的说明。它是所有关于如何签订了数字保存在记忆。做一个搜索两-补充符号表示的更多的细节,但这里的基本知识。

因此,让我们来看看65529十进制。它可以表示为 FFF9h 在十六.我们还可以表示,在二元为:

11111111 11111001

当我们声明 short zz = 65529;, 编译器解释65529作为签署了价值。两人-补充符号,顶部位表明是否签署了价值是积极的还是消极的。在这种情况下,可以看到顶点是 1, ,所以它将被视为负数。这就是为什么它打印出 -7.

对于一个 unsigned short, 我们不关心,因为它的标志 unsigned.因此,当我们打印出来的使用 %d, 我们使用的所有16位,所以它解释为 65529.

要了解为什么,您需要知道CPU使用两者的补充代表签名的数字(也许不是全部,而是很多)。

    byte n = 1; //0000 0001 =  1
    n = ~n + 1; //1111 1110 + 0000 0001 = 1111 1111 = -1

而且,根据您的CPU,INT类型和未签名的INT可以具有不同的尺寸。做这样的特定事情时:

   #include <stdint.h>
   int8_t ibyte;
   uint8_t ubyte;
   int16_t iword;
   //......

值65529U和-7的表示对于16位INT是相同的。只有对位的解释是不同的。

对于较大的INT和这些值,您需要签名扩展;一种方法是逻辑操作

int y = (int )(x | 0xffff0000u); // assumes 16 to 32 extension, x is > 32767

如果速度不是问题,或者划分在您的处理器上很快,

int y = ((int ) (x * 65536u)) / 65536;

乘偏移左16位(同样,假设16至32个延伸),而划分向右移动以维持符号。

您期待您的 int 类型为16宽,在这种情况下,您确实会得到负值。但是很可能是32位宽,所以签名 int 可以代表65529。您可以通过打印检查 sizeof(int).

要回答上面评论中发布的问题 - 尝试这样的事情:

unsigned short int x = 65529U;
short int y = (short int)x;

printf("%d\n", y);

或者

unsigned short int x = 65529U;
short int y = 0;

memcpy(&y, &x, sizeof(short int);
printf("%d\n", y);

由于将无符号值转换为表示正数转换的正数可以通过将最重要的位设置为0来完成。因此,程序不会将其解释为两个补充值。一个警告是,这将丢失有关未签名类型接近最大数字的信息。

template <typename TUnsigned, typename TSinged>
TSinged UnsignedToSigned(TUnsigned val)
{
    return val & ~(1 << ((sizeof(TUnsigned) * 8) - 1));
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top