以2為基數表示的數字稱為二進制數,可以使用二進制數將任何整數表示為1和0的一個組合,這種系統非常適合於數字計算機使用。
15.1.1 二進制整數
描述存儲器芯片和數據傳輸率時使用的字節指8位字節。
最小的二進制數是00000000,或一個簡單的0.一個字節可以存儲的數的范圍是0到255.
通過改變對位模式的解釋方式,一個字節可以存儲從-128到+127之間的整數。
15.1.2 有符號整數
有符號數的表示方法是由硬件決定,而不是由C決定。其中最簡單的方法就是保留1位來表述數的符號。
但是該方法有一個確定就是有兩個零+0和-0.
二進制補碼避免了這個問題。
兩種方法的區別在於確定該負數值的方法。從一個9位組合100000000減去一個負數的位組合,結果是該負數值的數量。
例如一個負數的位組合為10000000,值為100000000-10000000 即10000000 128,因此該數為-128. 同理10000001是-127,11111111是-1.
15.1.3 二進制浮點數
浮點數分兩部分存儲:一個二進制小數和一個二進制指數。
像1/3這樣的許多小數不能用十進制計數法精確的表示。同樣,許多小數也不能用二進制計數法精確表示。
要在計算機中表示一個浮點數,需要留出若干位存放一個二進制小數,其它位存放一個指數。
15.2.1 位邏輯運算符
4個位運算符用於整形數據,包括char。這些運算符稱為位運算符的原因是它們對每位進行操作,而不影響左右兩側的位。
一、二進制反碼或按位取反:~
一元運算符~將每個1變為0,每個0變為1.
二、位與:&
二進制運算符&通過對兩個操作數逐位進行比較產生一個新值。對於每個位,只有兩個操作數的對應位都為1時結果才為1.
三、位或:|
二進制運算符&通過對兩個操作數逐位進行比較產生一個新值。對於每個位,如果其中任意操作數中對應的位為1時結果為1.
四、位異或^
二進制運算符&通過對兩個操作數逐位進行比較產生一個新值。對於每個位,如果操作數中對應的位有一個為1(但是不都為1)那麼結果為1.
15.2.2 用法:掩碼
“位與”運算符通常跟掩碼一起使用。掩碼是某些位設為開而某些位設置為關的位組合。
假設定義符號常量MASK為2,即二進制的00000010,只有位1是非零。
那麼flags&=MASK;這個語句將導致flags的除位1之外的所有位都被設為0.
因為掩碼中的零覆蓋了flags中相應的位,所以該過程成為“使用掩碼”。
15.2.3 用法:打開位
有時,您可能需要打開一個值中特定的位,同時保持其它位不變。
例如,MASK其位1設為1,下列語句中將flags中的位1設為1,並保留其它所有位不變:flags|=MASK;
15.2.4 用法:關閉位
有時,您可能需要關閉一個值中特定的位,同時保持其它位不變。
例如,MASK其位1設為1,下列語句中將flags中的位1設為0,並保留其它所有位不變:flag&=~MASK;
15.2.5 用法:轉置位
轉置一個位表示如果該位打開則將其關閉,否則將其打開。
該值中對應掩碼位為1的位被轉置,對應掩碼位為0的位則不改變。flag^=MASK;
15.2.6 用法:查看一位的值
假設您希望查看一位的值。例如flag的位1是否為1?
if((flag&MASK)==MASK)
15.2.7 移位運算符
一、左移
左移運算符<<將其左側操作數的值的每位向左移動,移動的位數由其右側操作數指定。空出的位用0填充,並且丟棄移出左側操作數末端的位。(10001010)<<2 ----00101000
二、右移
左移運算符<<將其左側操作數的值的每位向左移動,移動的位數由其右側操作數指定。丟棄移出右側操作數右端的位。對於unsigned類型,使用0填充左端空出的位。對於有符號類型,結果依賴於機器。
三、用法:移位運算符
移位運算能夠提供快捷、高效的對2的冪的乘法和除法。
number<<n //number乘以2的n次冪
number>>n //如果number非負,則用number除以2的n次冪
例如:假設您希望使用一個unsigned long值代表顏色值,其中低位字節存放紅色亮度,下一字節存放綠色亮度,第三個字節存放藍色亮度。假設您隨後希望每種顏色的亮度存儲在各自的unsigned char變量中
#define BYTE_MASK 0xff
unsigned long color=0x002a162f;
unsigned char blue,green,red;
red=color&BYTE_MASK;
green=(color>>8)&BYTE_MASK;
blue=(color>>16)&BYTE_MASK;
四、用法:反轉一個值中的最後n位
int invert_end(int num,int bits)
{
int mask=0;
int bitval=1;
while(bits-->0)
{
mask|=bitval;
bitval<<1;
}
return num ^mask;
}
對位進行操作的第二種方法是使用位字段,位字段是一個signed int或unsigned int中一組相鄰的位。位字段由一個結構聲明建立,該結構聲明為每個字段提供標簽,並決定字段的寬度。
例如,以下聲明建立了4個1位字段:
struct{
unsigned int autfd: 1;
unsigned int bldfc: 1;
unsigned int undln: 1;
unsigned int itals: 1;
}prnt;
可以使用普通的結構成員運算符將值賦給單獨的字段:例如prnt.itals=0;
因為每個字段都正好為1位,所以1和0是惟一可以用於賦值的值。變量prnt被存儲在一個Int大小的存儲單元中,但是在本例中僅有其中的4位被使用。
當然也可以創建不同位大小的字段。