面試題在文章第4節(jié)塞赂。在看面試題之前,可以先看一下1-3節(jié)的知識點昼蛀。
1. 補碼
Two's Complement(二補數(shù)宴猾、補碼)是對二進制數(shù)
的數(shù)學(xué)運算,運算過程為:對二進制序列每一位取反(0->1; 1->0)叼旋,再加1仇哆。
bits | 取反 | 補碼 |
---|---|---|
011 | 100 | 101 |
010 | 101 | 110 |
111 | 000 | 001 |
2. 計算機中有符號數(shù)的表示
計算機中的數(shù)值類型分為整數(shù)型和浮點數(shù)型,有符號數(shù)在最高位設(shè)置符號位夫植,其余低位均為數(shù)值位讹剔。數(shù)值位一律采用補碼形式存儲,并參與計算详民。采用補碼的形式表示有符號數(shù)至少有兩大好處延欠。
- 符號位和數(shù)值位統(tǒng)一參與運算,不用區(qū)分正沈跨、負由捎,加法和減法實現(xiàn)簡單;
- 數(shù)據(jù)的原碼和補碼之間的相互轉(zhuǎn)換不需要依賴額外硬件電路饿凛。
下面分別介紹有符號數(shù)的表示方法
2.1 整數(shù)
正整數(shù)
正整數(shù)的補碼是其二進制表示狞玛,與原碼相同软驰。
例如,在整數(shù)類型占用4字節(jié)(32位)的系統(tǒng)中心肪,+5的補碼是00000000 00000000 00000000 00000101
锭亏。最高位0
表示該數(shù)值為正數(shù),其余31位表示數(shù)值大小蒙畴。
負整數(shù)
負整數(shù)的補碼需要對其絕對值的二進制表示進行補碼運算贰镣。
例如,-5的補碼是11111111 11111111 11111111 11111011
膳凝。最高位為1
碑隆,表示該數(shù)值為負數(shù),其余31位表示數(shù)值大小蹬音。
在進行運算時上煤,CPU并不會區(qū)分是正數(shù)還是負數(shù),而是直接進行計算著淆,這正是前面介紹的符號位和數(shù)值位的統(tǒng)一劫狠。
例如,a=10, b=-5
永部,則a+b
的運算過程如下:
00000000 00000000 00000000 00001010 (10)
+ 11111111 11111111 11111111 11111011 (-5)
===========================================
00000000 00000000 00000000 00000101 (5)
如果独泞,a=1, b=5
,則a-b
首先轉(zhuǎn)換成加法a+(-b)
苔埋,再進行計算懦砂,過程如下:
a-b ==> a+(-b)
00000000 00000000 00000000 00000001 (1)
+ 11111111 11111111 11111111 11110110 (-10)
===========================================
11111111 11111111 11111111 11110111 (-9)
對于正整數(shù)(最高位為1),將非符號位的二進制位直接轉(zhuǎn)換成十進制组橄,就表示該正數(shù)的實際大小荞膘。如果一個數(shù)是負整數(shù),如何將其補碼轉(zhuǎn)換成十進制大小呢玉工?補碼運算即可羽资。
例如上面的11111111 11111111 11111111 11110111
,最高位符號位是1
遵班,所以該數(shù)為負數(shù)屠升,補碼運算之后為00000000 00000000 00000000 00001001
,大小為9狭郑,所以表示-9
腹暖。
2.2 浮點數(shù)
pass
3. 為什么是補碼?
為什么兩個數(shù)相減a-b
用補碼形式a+(-b)
進行計算的結(jié)果是正確的愿阐?不妨看一下對b進行補碼的過程絕對值的二進制序列取反微服,再加1
趾疚。取反在計算機的邏輯電路中就是開關(guān)的閉合狀態(tài)取反即可缨历,即1->0以蕴,0->1。如果用數(shù)學(xué)算式表達的話辛孵,對一個bit位b的取反運算可以寫成
取反b = 1-b (*)
b=0時丛肮,取反b為1,1-b=1魄缚;
b=1時宝与,取反b為0,1-b=0冶匹;
所以算是(*)可以表達取反運算
綜上习劫,a-b
的計算過程可表達為(8bit為例)
a-b == a+(-b) == a+(11111111-b+1) == a+(b的補碼形式)
在8bit系統(tǒng)中,11111111 + 1 == 00000000嚼隘,溢出诽里。
所以,a+(11111111-b+1) = a+(0-b) = a - b
可以看出飞蛹,補碼運算的實現(xiàn)效果巧妙地利用了因計算機系統(tǒng)位數(shù)限制而產(chǎn)生的溢出現(xiàn)象谤狡。
4. 一個C++面試題
下面代碼打印多少?
#include <iostream>
int main(int argc, char **argv)
{
std::cout << 25u - 50;
return 0;
}
答案是4294967271
卧檐。
25u
是unsigned int
類型墓懂,50為int
類型。在這兩種操作數(shù)進行-
運算時霉囚,int
被提升為unsigned int
型捕仔,運算變?yōu)?code>25u - 50u,結(jié)果也應(yīng)該是unsigned int
類型佛嬉。經(jīng)過對-50u
進行補碼運算后帶入加法運算逻澳,-25
的二進制表示形式被存入內(nèi)存,即11111111 11111111 11111111 11100111
(int為32位)暖呕,在打印時按無符號數(shù)處理斜做,則直接轉(zhuǎn)換成十進制正整數(shù)為4294967271
。
11111111 11111111 11111111 11100111 =
2^31 + 2^30 + ... + 2^5 + 2^2 + 2^1 + 2^0 =
2^5(1-2^27) / (1-2) + 7 =
4294967271
更多面試題和答案:24 Essential C++ Interview Questions