對二值信號進(jìn)行存儲和執(zhí)行計算的電子電路非常簡單和可靠。
重要的三中數(shù)字表示:
- 無符號 -- 基于傳統(tǒng)的二進(jìn)制表示法,表示大于或者等于零的數(shù)字。
- 補(bǔ)碼 -- 表示有符號整數(shù)的最常見方式,有符號整數(shù)就是可以為正或者為負(fù)得數(shù)字。
- 浮點(diǎn)數(shù) -- 表示實(shí)數(shù)的科學(xué)記數(shù)法的以二為基數(shù)的版本。
計算機(jī)的表示法是用有限數(shù)量的位來對一個數(shù)字編碼。由于表示的精度有限,浮點(diǎn)運(yùn)算是不可結(jié)合的。
整數(shù)運(yùn)算和浮點(diǎn)運(yùn)算會有不同的數(shù)學(xué)屬性是因?yàn)樗麄兲幚頂?shù)字表示有限性的方式不同--整數(shù)的表示雖然只能編碼一個相對較小的數(shù)值范圍,但是這種表示是精確的;而浮點(diǎn)數(shù)雖然可以編碼一個較大的數(shù)值范圍,但是這種表示只是近似的。
整數(shù)運(yùn)算--精確的。
浮點(diǎn)運(yùn)算--非精確的。
2.1 信息存儲
大多數(shù)計算機(jī)使用8位的塊,或者字節(jié),作為最小的可尋址的存儲器單位,而不是在存儲器中訪問單獨(dú)的位。
C語言中一個指針的值(無論是指向一個整數(shù)、一個結(jié)構(gòu)或某個其他程序?qū)ο螅┒际且阅硞€存儲塊的第一個字節(jié)的虛擬地址。
在C語言中,以0x或者0X開頭得數(shù)字常量被認(rèn)為是十六進(jìn)制的值。字符A~F既可以是大寫,也可以是小寫,甚至是大小寫混合。
十六進(jìn)制轉(zhuǎn)換為二進(jìn)制:首先將每4位分為一組,再把它轉(zhuǎn)換為十六進(jìn)制。不過需要注意,如果位得總數(shù)不是4的倍數(shù),最左邊得一組可以少于4位,前面用0補(bǔ)足,然后將每個4位組轉(zhuǎn)換為相應(yīng)的十六進(jìn)制數(shù)字。
當(dāng)值x是2的非負(fù)整數(shù)n次冪時,也就是x=2^n,我們可以很容易地將x攜程十六進(jìn)制形式,只要記?。?br>
x的二級制表示就是1后面跟n個0.
十六進(jìn)制數(shù)字0代表4個二級制0。
所以,當(dāng)n表示成i+4j的形式,其中0≤i≤3時,我們可以把寫成開頭得十六進(jìn)制數(shù)字為 1(i=0)、2(i=1)、4(i=2)、8(i=3),后面跟隨著j個十六進(jìn)制的0.
比如: x=2048=2^11
于是有: n = 11 = 3+4*2 從而得到十六進(jìn)制表示 0x800
2.1.2 字
每臺計算機(jī)都有一個字長(word size),指明整數(shù)和指針數(shù)據(jù)的標(biāo)稱大?。╪ominal size)。因?yàn)樘摂M地址是通過一個字來編碼的。所以字長決定的最重要的系統(tǒng)參數(shù)就是虛擬地址空間得最大大小。也就是說,對于一個字長為w位得機(jī)器而言,虛擬地址的范圍是0~2(w-1),程序最多訪問2w個字節(jié)。
2.1.3 數(shù)據(jù)大小
C的數(shù)據(jù)類型大小:
char -- 1個字節(jié)。
short int -- 2個字節(jié)
int -- 4個字節(jié)
long int-- 使用機(jī)器的全字長,如果是32位則4字節(jié),如果64為則8字節(jié)
long long int-- 允許64位整數(shù),使用8個字節(jié)。對于32位機(jī)器而言,編譯器必須把這種數(shù)據(jù)類型的操作編譯成一系列32位操作的代碼。
float -- 4個字節(jié)
double-- 8個字節(jié)
char* -- 機(jī)器的全字長,32位是4個字節(jié),64位是8個字節(jié)。
需要注意:許多程序員假設(shè)一個聲明為int類型得程序?qū)ο竽鼙挥脕泶鎯σ粋€指針。這在大多數(shù)32位得機(jī)器上能正常工作,但是在一臺64位得機(jī)器上卻會導(dǎo)致問題。(因?yàn)?4位下int是4字節(jié),而指針是8字節(jié)。)
2.1.4 尋址和字節(jié)順序
在幾乎所有的機(jī)器上,多字節(jié)對象都被存儲為連續(xù)的字節(jié)序列,對象的地址為嗦使用字節(jié)中最小的地址。
例如:一個類型為int得變量x的地址為0x100,也就是說,地址表達(dá)式&x的值為0x100。那么,x的4個字節(jié)被存儲在存儲器的0x100,0x101,ox102,ox103位置。
在存儲器存儲中,有大端法和小端法的區(qū)分:
大端法 -- 最高有效字節(jié)在最前面。IBM和SUN采用此種規(guī)則。
小端法 -- 最低有效字節(jié)在最前面。Intel兼容機(jī)采用此種規(guī)則。
許多比較新的微處理器使用雙端法,也就是說可以把他們配置為大端或者小端的機(jī)器運(yùn)行。
對于int類型的x,位于地址0x100處,它得十六進(jìn)制值為0x1234567 ,地址范圍為0x100~0x103字節(jié),其排列順序依賴于機(jī)器類型。
大端法 -- 01(ox100) 23(0x101) 45(0x102) 67(0x103)
小端法 -- 67(ox100) 45(0x101) 23(0x102) 01(0x103)
一般情況下,機(jī)器所使用的字節(jié)順序?qū)ξ覀儊碚f是透明的,不可見的。無論使用哪種類型的機(jī)器編譯程序都會得到同樣的結(jié)果。
除非在編寫網(wǎng)絡(luò)程序的時候,才需要注意這個問題。
為了避免這類問題,網(wǎng)絡(luò)應(yīng)用程序的代碼編寫必須遵守已建立的關(guān)于字節(jié)順序的規(guī)則,以確保發(fā)送機(jī)器將它得內(nèi)部表示轉(zhuǎn)換成網(wǎng)絡(luò)標(biāo)準(zhǔn),而接收方機(jī)器則將網(wǎng)絡(luò)標(biāo)準(zhǔn)轉(zhuǎn)換為它得內(nèi)部表示。
對于任一位向量a,有a^a =0 。
2.1.9 C語言中的位運(yùn)算和邏輯運(yùn)算
C語言中的位運(yùn)算:
| 或
& 與
~ 取反
^ 異或 當(dāng)p=1且q=0,或者p=0且q=1時, p^q = 1
C語言中的邏輯運(yùn)算:
|| 或 or
&& 與 and
! 非 not
邏輯運(yùn)算認(rèn)為所有非零的參數(shù)都表示true,而參數(shù)0表示false。
邏輯運(yùn)算&&和||與他們對應(yīng)的位級運(yùn)算&和|之間的第二個重要的區(qū)別是,如果對第一個參數(shù)求值就能確定表達(dá)式的結(jié)果,那么邏輯運(yùn)算符就不會對第二個參數(shù)求值。
2.1.0 C語言中的移位運(yùn)算
左移、右移
右移支持兩種:邏輯右移和算術(shù)右移。
邏輯右移在左端補(bǔ)0。
算術(shù)右移是在左端補(bǔ)最高有效位的值。
x = 01100001 10010101
x》4 (邏輯右移) 00000110 00001001
x》4 (算術(shù)右移) 00000110 11111001
C語言中并沒有明確定義應(yīng)該使用哪種類型的右移。對于無符號數(shù)據(jù)(也即是以 unsigned聲明開通的整型對象),邏輯右移是必須得。
幾乎所有的編譯器、機(jī)器組合都對有符號數(shù)據(jù)使用算術(shù)右移,且許多程序員也都假設(shè)機(jī)器會使用算術(shù)右移。
另外,Java對于如何進(jìn)行右移有明確的定義。
x》k 會將x算術(shù)右移k個位置。
x>>>k 會對x做邏輯右移。
在許多機(jī)器上,當(dāng)移位位數(shù)k超過了機(jī)器的字長w時,移位移的是w mod k 位。
比如在32位機(jī)器上移位40位,則只是移8位。
int lval = oxFEDCBA98 <<32 = oxFEDCBA98
int aval = oxFEDCBA98 >>36 = 0xFFEDCBA9
unsigned uval = oxFEDCBA98u >>40 = ox00FEDCBA
不過C語言沒有對這種行為進(jìn)行保障,所以移位數(shù)量應(yīng)該保持小于字長。
另一方面,Java特別要求位移數(shù)量應(yīng)該按照之前講的求模的方法來計算。
加法減法的優(yōu)先級比移位運(yùn)算要高。
所以: 1<<2+3<<4 = 1<<(2+3)<<4 = (1<<(2+3))<<4 = 512
在拿不準(zhǔn)時,請用括號表明運(yùn)算順序。