![](/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.