将unsigned int转换为signed int C.

我试图将65529unsigned int转换为signed int 。 我尝试做这样的演员:

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

但是当它应该返回-7时, y仍然返回65529。 这是为什么?

看起来你期望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  

我知道这是一个老问题,但它是一个很好的问题,那么这个怎么样?

 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十进制。 它可以用hex表示为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和unsigned int类型的大小可以不同。 在做这样的具体事情时:

  #include  int8_t ibyte; uint8_t ubyte; int16_t iword; //...... 

对于16位整数,值65529u和-7的表示相同。 只有比特的解释是不同的。

对于较大的int和这些值,您需要签署extend; 一种方式是逻辑运算

 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);