![](/img/trans.png)
[英]How to convert an unsigned 24 bit int into a signed int and sign extend to 32 bits?
[英]Negative numbers: How can I change the sign bit in a signed int to a 0?
我在想这个世界是有效的,但事实并非如此:
int a = -500;
a = a << 1;
a = (unsigned int)a >> 1;
//printf("%d",a) gives me "2147483148"
我的想法是左移会移除最左边的符号位,所以右移它作为无符号整数将保证它是一个逻辑移位而不是算术。 为什么这不正确?
也:
int a = -500;
a = a << 1;
//printf("%d",a) gives me "-1000"
TL; DR:最简单的方法是使用<stdlib.h>
的abs
函数。 答案的其余部分涉及在计算机上表示负数。
负整数(几乎总是)以2的补码形式表示 。 (见下面的注释)
获得数字否定的方法是:
以500
为例,
500
: _000 0001 1111 0100
( _
是符号位的占位符)。 _111 1110 0000 1011
1
: _111 1110 0000 1011 + 1 = _111 1110 0000 1100
。 当您将符号位替换为零时,这与您获得的2147483148
相同。 0
表示正数, 1
表示负数: 1111 1110 0000 1100
。 (这与上面的2147483148
不同。你得到上述值的原因是因为你获得了MSB)。 反转标志是一个类似的过程。 如果您使用16位或32位数字导致您看到的大值,那么您将得到领先的数字。 在每种情况下LSB应该相同。
注意:有些机器具有1的补码表示,但它们是少数。 2的补码通常是首选,因为0
具有相同的表示,即-0
和0
在2的补码表示法中表示为全零。
左移负整数调用未定义的行为,因此您不能这样做。 你可以使用你的代码,如果你做a = (unsigned int)a << 1;
。 你得到500 = 0xFFFFFE0C
,左移1 = 0xFFFFFC18
。
a = (unsigned int)a >> 1;
确实保证逻辑移位,所以你得到0x7FFFFE0C
。 这是小数2147483148。
但这是不必要的复杂。 更改符号位的最佳和最便携的方法是a = -a
。 任何其他代码或方法都值得怀疑。
但是如果你坚持做点蠢事,你也可以做点什么
(int32_t)a & ~(1u << 31)
这可以移植到32位系统,因为(int32_t)
保证二进制补码,但1u << 31
假设32位int
类型。
演示:
#include <stdio.h>
#include <stdint.h>
int main (void)
{
int a = -500;
a = (unsigned int)a << 1;
a = (unsigned int)a >> 1;
printf("%.8X = %d\n", a, a);
_Static_assert(sizeof(int)>=4, "Int must be at least 32 bits.");
a = -500;
a = (int32_t)a & ~(1u << 31);
printf("%.8X = %d\n", a, a);
return 0;
}
当您放入“另外”部分时,在第一次左移1位后,DOES按预期反映-1000。
问题在于你的转换为unsigned int。 如上所述,负数表示为2的补码,意味着符号由最左位(最高有效位)确定。 当转换为unsigned int时,该值不再表示符号,但会增加int可以采用的最大值。
假设32位整数,MSB用于表示-2 ^ 31(= -2147483648),现在在无符号整数中表示正2147483648,增加2 * 2147483648 = 4294967296.将此值添加到原始值-1000并且您得到4294966296.右移将此除以2,然后到达2147483148。
希望这可能会有所帮助:( 使用C从二进制表示中打印一个int修改打印函数)
void int2bin(int a, char *buffer, int buf_size) {
buffer += (buf_size - 1);
for (int i = buf_size-1; i >= 0; i--) {
*buffer-- = (a & 1) + '0';
a >>= 1;
}
}
int main() {
int test = -500;
int bufSize = sizeof(int)*8 + 1;
char buf[bufSize];
buf[bufSize-1] = '\0';
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: -500 (4294966796): 11111111111111111111111000001100
test = test << 1;
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: -1000 (4294966296): 11111111111111111111110000011000
test = 500;
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: 500 (500): 00000000000000000000000111110100
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.