無(wú)符號(hào)編碼:基于傳統(tǒng)的二進(jìn)制表示法,表示大于或等于0的數(shù)字
補(bǔ)碼:有符號(hào)整數(shù)的常見(jiàn)方式(可正可負(fù))
浮點(diǎn)數(shù):表示實(shí)屬的科學(xué)計(jì)數(shù)法的以2為基數(shù)的版本
整數(shù)的運(yùn)算滿足整數(shù)運(yùn)算的許多性質(zhì)但浮點(diǎn)運(yùn)算有完全不同的數(shù)學(xué)屬性。
信息存儲(chǔ)
- 字節(jié)作為最小的可尋址的內(nèi)存單位。
- 內(nèi)存可視為一個(gè)非常大的字節(jié)數(shù)組,稱為虛擬內(nèi)存。內(nèi)存中的每個(gè)字節(jié)都由一個(gè)唯一的數(shù)字來(lái)表示,稱為地址。所有可能地址的集合稱為虛擬地址空間。
- 每個(gè)程序?qū)ο罂梢暈橐粋€(gè)字節(jié)塊,而程序本身就是一個(gè)字節(jié)序列。
- C語(yǔ)言的指針有兩個(gè)方面:值和類型。值表示某個(gè)對(duì)象的位置,類型表示那個(gè)位置上所存儲(chǔ)對(duì)象的類型。
1.1 十六進(jìn)制表示法
1.1.1 二進(jìn)制、十進(jìn)制和十六進(jìn)制的一般表示法

- 竅門(mén):記住A、C、F相應(yīng)的十進(jìn)制值,而其他的值可以根據(jù)這三個(gè)值的相對(duì)關(guān)系來(lái)計(jì)算得出。
- 對(duì)于二進(jìn)制轉(zhuǎn)化為十六進(jìn)制,先將二進(jìn)制數(shù)以4位為一組進(jìn)行分割,若二進(jìn)制位總數(shù)不是4的倍數(shù),則最左邊的一組可少于4位,缺少的位數(shù)用0補(bǔ)全。然后再將每個(gè)4位轉(zhuǎn)換為對(duì)應(yīng)的十六進(jìn)制數(shù)字即可。
- 對(duì)于各種進(jìn)制之間的相互轉(zhuǎn)換,除k取余法均適用。注意,除k取余法得到的余數(shù),余數(shù)需從下往上取出,并從左往右寫(xiě)出結(jié)果
- 十進(jìn)制加減法使用的方法適用于十六進(jìn)制,只是十進(jìn)制以10為基數(shù),十六進(jìn)制以16為基數(shù)。(即滿十進(jìn)一改成滿十六進(jìn)一,數(shù)字加10變成加16,運(yùn)算方式不變)
1.1.2 對(duì)于2的非負(fù)整數(shù)次冪的十六進(jìn)制轉(zhuǎn)換法

1.2 字?jǐn)?shù)據(jù)大小
- 字長(zhǎng)指明了指針數(shù)據(jù)的標(biāo)稱大小,字長(zhǎng)決定的系統(tǒng)參數(shù)是虛擬地址空間的大小。
對(duì)于一個(gè)字長(zhǎng)為w位的機(jī)器來(lái)說(shuō),虛擬地址范圍為0 ~
,程序最多訪問(wèn)
個(gè)字節(jié)(即虛擬地址空間的大?。?。
比如,32位字長(zhǎng)的機(jī)器,虛擬地址空間為4千兆字節(jié)(4GB),64位字長(zhǎng)的機(jī)器,虛擬地址空間為16GB 。64位機(jī)器可以運(yùn)行32位機(jī)器編譯的程序,但是用64位機(jī)器編譯的程序就只能在64位機(jī)器上運(yùn)行。因此,32位程序和64位程序,區(qū)別在于程序如何編譯,而不是運(yùn)行的機(jī)器類型。
-
C語(yǔ)言中各種數(shù)據(jù)類型分配的字節(jié)數(shù)如圖:
C語(yǔ)言中數(shù)據(jù)類型和字節(jié)數(shù)分配情況- 整數(shù)有符號(hào),可以表示負(fù)數(shù)、零和正數(shù),無(wú)符號(hào)時(shí),只能表示非負(fù)數(shù)。
- int32_t和int64_t,分別是4個(gè)字節(jié)和8個(gè)字節(jié),是確定大小的整數(shù)類型
- 單精度(float)和雙精度(double)分別使用4字節(jié)和8字節(jié)
1.3 尋址和字節(jié)順序
- 兩個(gè)規(guī)則:這個(gè)對(duì)象的地址是什么,在內(nèi)存中如何排列這些字節(jié)
對(duì)象的地址是什么
多字節(jié)對(duì)象都被存儲(chǔ)為連續(xù)的字節(jié)序列,對(duì)象的地址為所使用字節(jié)中最小的地址。
內(nèi)存中如何排列字節(jié)
- 小端法:最低有效字節(jié)在最前面的方式
- 大端法:最高有效字節(jié)在最前面的方式
此處注意最高/低有效字節(jié)和最前面的定義。比如一個(gè)字0x01234567中,最高有效字節(jié)為0x01,最低有效字節(jié)為0x67。"最前面"的意思是指,地址從小到大計(jì)算,較小的一端為"前面"。如在地址0x100~0x103中存放上述的數(shù)據(jù),0x100為"前面"。其大端法和小端法的字節(jié)排列如下圖:
大端法和小端法示例圖Android和IOS兩種操作系統(tǒng)采用的是小端法。
字節(jié)順序帶來(lái)的問(wèn)題:
采用不同端法的機(jī)器通過(guò)網(wǎng)絡(luò)傳輸二進(jìn)制數(shù)據(jù)時(shí),字節(jié)會(huì)變成反序的。解決辦法是相關(guān)的網(wǎng)絡(luò)應(yīng)用程序按照已建立的字節(jié)順序的規(guī)則,發(fā)送方將它的內(nèi)部表示轉(zhuǎn)換成網(wǎng)絡(luò)標(biāo)準(zhǔn),接收方將網(wǎng)絡(luò)標(biāo)準(zhǔn)轉(zhuǎn)換成接收方的內(nèi)部表示。
當(dāng)閱讀表示整數(shù)數(shù)據(jù)的字節(jié)序列時(shí),字節(jié)順序的不一樣會(huì)導(dǎo)致書(shū)寫(xiě)的字節(jié)順序和讀取字節(jié)順序相反
-
當(dāng)編寫(xiě) 規(guī)避了正常的類型系統(tǒng) 的程序時(shí),會(huì)帶來(lái)問(wèn)題。如 通過(guò)強(qiáng)制類型轉(zhuǎn)換,或聯(lián)合來(lái)允許一種數(shù)據(jù)類型來(lái)引用一個(gè)對(duì)象,而這種數(shù)據(jù)類型于創(chuàng)建這個(gè)對(duì)象時(shí)定義的數(shù)據(jù)類型不同。如圖所示:
類型轉(zhuǎn)換示例代碼? 此處將byte_pointer定義成一個(gè)指向類型為unsigned char對(duì)象的指針。當(dāng)調(diào)用show_bytes(int x)方法時(shí),程序?qū)的指針&x,強(qiáng)制轉(zhuǎn)換成unsigned char*。這樣得到的轉(zhuǎn)換值,將會(huì)被程序看成指向一個(gè)字節(jié)序列,而不是指向一個(gè)原始數(shù)據(jù)類型int的對(duì)象。然后,這個(gè)被強(qiáng)制轉(zhuǎn)換的指針,將會(huì)被看成是對(duì)象使用的最低字節(jié)地址。
1.4 表示字符串
- C語(yǔ)言中字符串被編碼成一個(gè)以null(值為0)字符結(jié)尾的字符數(shù)組。如字符串"12345",其ASCII碼為31 32 33 34 35 00,該 字符串長(zhǎng)度為6,包含終止符。
- 十進(jìn)制數(shù)字x的ASCII碼是0x3x,如數(shù)字1的ASCII碼是0x31,2的ASCII碼是0x32等。
- 字母'a'-'z'的ASCII碼范圍是0x61~0x7A。
1.5 表示代碼
- 不同的機(jī)器類型使用不同的且不兼容的指令和編碼方式。即使時(shí)完全一樣的進(jìn)行,運(yùn)行在不同操作系統(tǒng)的編碼規(guī)則會(huì)有不同,因此得到的二進(jìn)制代碼時(shí)不兼容的。
1.6 布爾代數(shù)
- 布爾運(yùn)算 ~ 對(duì)應(yīng)邏輯運(yùn)算NOT,命題邏輯符號(hào)
。當(dāng)P非真時(shí),
P為真。
- 布爾運(yùn)算 & 對(duì)應(yīng)邏輯運(yùn)算AND,命題邏輯符
。當(dāng)P、Q均為真時(shí),P
Q為真。
- 布爾運(yùn)算 | 對(duì)應(yīng)邏輯運(yùn)算OR,命題邏輯符
。當(dāng)P或Q為真時(shí),P
Q成立。
- 布爾運(yùn)算 ^ 對(duì)應(yīng)邏輯運(yùn)算異或,命題邏輯符
。當(dāng)P或Q為真,但不同時(shí)為真時(shí),P
Q成立
- 加法逆元屬性:每個(gè)值x都存在一個(gè)加法逆元-x,使得x+(-x)=0。在布爾運(yùn)算中的加法是
,每個(gè)元素的加法逆元是它本身,即a ^ a=0。另外還有(ab)a=b的特點(diǎn)。
位向量
- 位向量是固定長(zhǎng)度為
,由0和1 組成的串。即一串比特。
- 應(yīng)用:
- 表示有限集合,存在記為1,不存在記為0。
- 對(duì)集合進(jìn)行編碼。在計(jì)算機(jī)中可以有選擇地使能或屏蔽一些信號(hào)。
1.7 C語(yǔ)言中的位級(jí)運(yùn)算
C語(yǔ)言中通常對(duì)十六進(jìn)制數(shù)進(jìn)行位運(yùn)算。如0x69&0x55, ~0x41等。確定這樣一個(gè)位級(jí)表達(dá)式的結(jié)果的辦法,就是將十六進(jìn)制的參數(shù)擴(kuò)展成二進(jìn)制并執(zhí)行二進(jìn)制運(yùn)算,然后再轉(zhuǎn)換回十六進(jìn)制。
-
第二個(gè)用法,實(shí)現(xiàn)掩碼運(yùn)算。例子如圖所示:
位級(jí)運(yùn)算的應(yīng)用-掩碼運(yùn)算
1.8 C語(yǔ)言中的邏輯運(yùn)算
- C語(yǔ)言中的 || 、&&、!分別對(duì)應(yīng)于命題邏輯中的OR、AND、NOT。邏輯運(yùn)算認(rèn)為所有非0參數(shù)都為T(mén)RUE,參數(shù)0表示FALSE,邏輯運(yùn)算返回1或0。
- 按位運(yùn)算和邏輯運(yùn)算的區(qū)別:
- 按位運(yùn)算是逐個(gè)比特位進(jìn)行邏輯運(yùn)算,邏輯運(yùn)算是整個(gè)數(shù)表示為0或1 才進(jìn)行運(yùn)算。按位運(yùn)算只有參數(shù)被限制為0或1 時(shí),才與邏輯運(yùn)算有相同的行為。 比如0x69 && 0x55 ,兩個(gè)參數(shù)都會(huì)認(rèn)為是1,所有這個(gè)與邏輯運(yùn)算的結(jié)果是1。
- 邏輯運(yùn)算的第一個(gè)參數(shù)求值就能確定表達(dá)式結(jié)果時(shí),就不會(huì)對(duì)后面的參數(shù)進(jìn)行求值。比如, a&&5/a,就不會(huì)出現(xiàn)除數(shù)為0的情況。
1.9 C語(yǔ)言中的移位運(yùn)算
設(shè)操作數(shù)為x,一共有 位,移動(dòng)的位數(shù)為k,0
k
-1。
- 左移運(yùn)算:x向左移動(dòng)k位,丟棄最高的k位,并在右端補(bǔ)k個(gè)0。左移運(yùn)算是從左至右可結(jié)合的。如 x<<j<<k
(x<<j) <<k。
- 右移運(yùn)算:分邏輯右移和算術(shù)右移。邏輯右移在左端補(bǔ)k個(gè)0,算術(shù)右移在左端補(bǔ)k個(gè)最高有效位的值。比如參數(shù)x=10010101,邏輯右移4位,得0000 1001;算術(shù)右移4位,得1111 1001。
總結(jié):在移位運(yùn)算中,只有算術(shù)右移在移位時(shí)補(bǔ)充最高有效位得值,其他移位運(yùn)算都是補(bǔ)0。幾乎所有機(jī)器都對(duì)有符號(hào)數(shù)使用算術(shù)右移,而對(duì)于無(wú)符號(hào)數(shù),使用的是邏輯右移。
C語(yǔ)言中并沒(méi)有明確定義有符號(hào)數(shù)該用哪種類型的右移。在Java中則有明確定義,x>>k表示將x算術(shù)右移k位,x>>>k表示對(duì)x邏輯右移k位。
當(dāng)位移k很大時(shí)怎么辦
如 int val = 0xFEDCBA98 >> 36,k=36,大于val的位數(shù)(32位),則此時(shí)計(jì)算k mod =4,則對(duì)val右移4位。這種行為C語(yǔ)言中沒(méi)有保證,在Java中的位移數(shù)量則會(huì)按照這個(gè)方法來(lái)計(jì)算。
另外,在C語(yǔ)言中,加減法運(yùn)算的優(yōu)先級(jí)比移位運(yùn)算的優(yōu)先級(jí)要高。



