1、機器級程式將儲存空間視為一個非常大的位元組數組,稱為虛擬儲存空間(virtual memory)。儲存空間的每個位元組都由一個唯一的數字來標識,稱為地址(address),所有可能地址的集合就稱為虛擬位址空間(virtual address space)。虛擬位址空間是一個展現給機器級程式的概念性映像(image),具體的實現使用的是隨機訪問儲存空間RAM,磁碟儲存,特殊硬體和OS軟體的結合,來為程式提供一個看上去統一的位元組數組。
2、指值有兩個方面:它的值和它的類型。它的值表示的是某個對象的位置,而它的類型表示那個位置上所儲存物件的類型(如int,float)。
3、每台電腦都有一個字長(word size),指明整數和指標資料的標稱(nominal size)大小。虛擬位址是以字來編碼的。對於一個字長為n位的機器來說,虛擬位址的範圍為0~2n-1,程式最多訪問2n個位元組。
如32位字長的電腦上,虛擬位址空間為4GB。
4、電腦和編譯器使用不同的方式來編碼數字。
小端(little endian):低地址存放低位元組。
大端(big endian):高地址存放低位元組。
網路應用程式的代碼編寫必須遵守已建立的關於位元組順序的規則,以確保發送方機器將它的內部表示轉換成網路標準,而接收方機器將網路標準轉換成它的內部表示。
範例程式碼
#include <iostream>#include "string"#include "cmath"#include "iomanip"using namespace std;typedef unsigned char* byte_pointer;void show_bytes(byte_pointer bpstart, int ilen){int iTempi;for (iTempi = 0; iTempi < ilen; iTempi++)printf("%.2x", bpstart[iTempi]);printf("\n");}void show_int(int ix){show_bytes((byte_pointer)&ix, sizeof(int));}void show_float(float fx){show_bytes((byte_pointer)&fx, sizeof(float));}void show_pointer(void *x){show_bytes((byte_pointer)&x, sizeof(void*));}int main(){int iTemp = 1234;show_int(iTemp);float fTemp = (float)iTemp;show_float(fTemp);int *pTemp = &iTemp;show_pointer(pTemp);return 1;}
5、C中的移位
移位元運算從左至右結合。
1)機器支援兩種形式的右移:邏輯的算術的。邏輯右移k位在左端補k個0,[0,...0,xn-1,xn-2,...]。算術右移是在左端補k個最高有效位的拷貝,[xn-1,...xn-1,xn-2,...]
對於無符號資料,右移必須是邏輯的,有符號數則兩者都可以,一般機器實現中實現為算術右移。
2)左移,就是移位後,在右邊補0。
6、要將一個無符號數轉換為一個更大的資料類型,只要簡單的在開頭添加0;這種運算稱為0擴充(zero extension)。要將一個二進位補碼數字轉換為一個更大的資料類型,執行符號擴充(sign extension),在表示中添加最高有效位的值。
7、在資料轉換中,由大資料轉換成小資料可能發生截斷。棄高k位。對於一個無符號數x,截斷它到k位的結果就相當於計算x mod 2k。
8、範圍0,≤x,y≤2w-1內的整數x,y,可以被表示成w位的無符號數字,它們的乘積x.y的取值範圍為0~(2w-1)2,這可能需要2w位來表示。
9、在大多數機器上,整數乘法指令相當慢,需要12或更多刻度,其他整數運算,如加法,減法,移位和位級運算,只需要1個刻度。因此編譯器使用的一項重要的最佳化就是試著用移位和加法運算的組合來代替乘以常數因子的乘法。
整數除法比乘法更慢,需要30或者更多的刻度,除以2的冪也可以用移位元運算來實現。我們可右移。對於無符號數和二進位補碼數,分別使用邏輯移位和算術移位來達到目的。
10、在當前的電腦中,整數是以補碼錶示的。
11、IA32處理器有特別的儲存空間元素,稱為寄存器,當計算或使用浮點數時,用來儲存浮點值。浮點數的取反就是對符號位取反。
關於浮點數,本書中講的比較零碎,可以參考國內教材中《電腦群組成原理》等相關書籍。
<Computer Systems:A Programmer's Perspective>