文章目錄
-
- 為什麼-n=~ (n-1)=~ n+1?
-
- 解答
- 結構體所占位元組數
-
- 解答
鑒于有些問題,大家有些疑惑。我會把大家問到的問題,整理在這個文章中,友善大家觀看。
為什麼-n=~ (n-1)=~ n+1?
解答
該問題來源于嵌入式軟體開發面試知識點總結P141(舊版本的,估計很多人手中應該沒有這個版本)。
原問題為:不用除法操作符如何實作兩個正整數的除法。
粉絲的疑問在于表達式-n=~ (n-1)=~ n+1 。解決這個問題的核心在于,要知道計算機中是如何存儲數值的。
在計算機系統中,數值一律用補碼來表示(存儲)。主要原因是使用補碼可以将符号位和其他位統一處理;同時,減法也可以按加法來處理。另外,兩個用補碼表示的數相加時,如果最高位(符号位)有進位,則進位被舍棄。
如何求補碼呢?
-
正數的補碼
與原碼相同。
+9的補碼是00001001。
-
負數的補碼
對其原碼逐位取反,但符号位除外;然後整個數加1。
-7的原碼為10000111,按位取反為11111000,加1可得11111001。是以-7的補碼是11111001。
補碼表示方式有很多,以上兩個例子都是使用8位的2進制來表示的。此外,還有16位2進制補碼表示形式,以及32位2進制補碼表示形式等。
如何快速求補碼?
從最低位開始至找到的第一個1均不變,符号位不變,這之間的各位“求反”(0變1;1變0)。
原碼:1010 1001 補碼:1101 0111。
舉例
下面,我們舉個例子驗證下上面的等式。假設n = 10,則可以得到下面的各個表達式。
n:10 = 00001010
-n:-10 = 11110110
n-1:9 = 00001001
~(n-1):-10 = 11110110
~n:-11 = 11110101
~n+1 = 11110110
代碼驗證
算的對不對呢?可以寫個代碼驗證下。
#include <stdlib.h>
#include <stdio.h>
int PrintBinary(int bi,int len){
int i=0;
while(i<len){
int tmp = 1;
//從最左位開始比較,該位是1
if((bi & (tmp<<(len-i-1))) != 0){
printf(" 1 ");
}
else{
printf(" 0 ");
}
i++;
}
printf("\n");
return 0;
}
int main()
{
int n = 10;
printf("n=%d\n",n);
PrintBinary(n,8);
printf("-n=%d\n",-n);
PrintBinary(-n,8);
printf("n-1=%d\n",n-1);
PrintBinary(n-1,8);
printf("~(n-1)=%d\n", ~(n-1));
PrintBinary(~(n-1),8);
printf("~n=%d\n", ~n);
PrintBinary(~n,8);
printf("~n+1=%d\n", ~n+1);
PrintBinary(~n+1,8);
return 0;
}
結果如下。
n=10
0 0 0 0 1 0 1 0
-n=-10
1 1 1 1 0 1 1 0
n-1=9
0 0 0 0 1 0 0 1
~(n-1)=-10
1 1 1 1 0 1 1 0
~n=-11
1 1 1 1 0 1 0 1
~n+1=-10
1 1 1 1 0 1 1 0
常用的位運算技巧
- -n=~ (n-1)=~ n+1
- 擷取整數n的二進制中最後一個1:n&(-n)或者n&~(n-1)。例如,n=010100,則-n=101100,n&(-n)= 000100。
- 去掉整數n的二進制中最後一個1:n&(n-1),如n=010100,n-1=010011,n&(n-1)=010000。
結構體所占位元組數
該問題來源于嵌入式軟體開發面試知識點總結P150(舊版本的,估計很多人手中應該沒有這個版本)。
原問題為:指針進行強制類型轉換後與位址進行加法運算,結果是什麼?
struct BBB
{
long num;
char *name;
short int data;
char ha;
short ba[5];
}*p;
在32位機器下, sizeof(struct BBB)=24。但是粉絲算的是28。
解答
char | 指針變量 | short int | int | unsigned int | float | double | long | long long | unsigned long | |
---|---|---|---|---|---|---|---|---|---|---|
32位 | 1 | 4 | 2 | 4 | 4 | 4 | 8 | 4 | 8 | 4 |
64位 | 1 | 8 | 2 | 4 | 4 | 4 | 8 | 8 | 8 | 8 |
這位粉絲估計是把資料類型所占位元組數記錯了。
對于32位系統:4+4+2+1+(1)+10+(2)=24
對于64位系統:8+8+2+1+(1)+10+(2)=32
括号中的數字,表示的是為了保證4位元組對齊需要填充的位元組數。