(一)信息的表示與處理

Chapter 2

# 信息的表示和處理 Bits Bytes & Intergers

## 位 整數(shù)

**為啥要用二進(jìn)制?二進(jìn)制有什么優(yōu)點(diǎn)?在現(xiàn)實(shí)中有哪些應(yīng)用?**

在計(jì)算機(jī)中,數(shù)據(jù)是以位/比特(bit)為單位儲(chǔ)存的,一個(gè)字節(jié)是8bit的數(shù)據(jù)塊,這個(gè)尺度是計(jì)算機(jī)設(shè)計(jì)早期確定的,所以沿用至今(_為什么這么設(shè)計(jì)?_ASCII `linux: man ascii`)

進(jìn)制轉(zhuǎn)換的操作要會(huì)哦,尤其是2進(jìn)制,10進(jìn)制,16進(jìn)制的相互轉(zhuǎn)化;其中二進(jìn)制數(shù)存在最高有效位(MSB),最低有效位(LSB),十六進(jìn)制和二進(jìn)制轉(zhuǎn)化極為方便.

> 這里我先插一嘴(哇哦)正蛙,我們要熟練掌握十六進(jìn)制和二進(jìn)制之間的轉(zhuǎn)化

**字長(zhǎng)(word size)**對(duì)于計(jì)算機(jī)內(nèi)存而言是很重要的概念,它標(biāo)識(shí)了的內(nèi)存地址的最大長(zhǎng)度,而**地址的表示范圍決定了內(nèi)存的上限**.我們常說(shuō)的 32 位系統(tǒng),其內(nèi)存地址空間最大為 4GB,不管你裝多少根內(nèi)存,能使用的就這么多,這是系統(tǒng)層面的限制,而更高級(jí)的 64 位系統(tǒng),其內(nèi)存上限達(dá)到 16EB,以人類目前的生產(chǎn)力,都很難湊出來(lái)這么大的內(nèi)存.目前銷售的計(jì)算機(jī),絕大多數(shù)都是 64 位系統(tǒng)了.

> 32位系統(tǒng)不能運(yùn)行64位程序,但是多虧AMD的x86-64架構(gòu),64位系統(tǒng)是可以運(yùn)行32位程序的.

由于在不同編譯器和系統(tǒng)上,int類型的長(zhǎng)度可能會(huì)不同,C99中解決了這個(gè)問(wèn)題,規(guī)定`int32_t`和`int64_t`來(lái)分別表示長(zhǎng)度為4和8的整型數(shù)值,但是long的數(shù)據(jù)長(zhǎng)度還是會(huì)根據(jù)32/64位系統(tǒng)變化.

計(jì)算機(jī)歷史上還有大小端的派別之分,大端即數(shù)據(jù)高位在小地址,低位在大地址,反之則為小端法.

而且Windows,Linux,IOS和Android都是小端法.

ANSCII只適合表示英文文本內(nèi)容,對(duì)于特殊符號(hào)很乏力,所以衍生了Unicode這一規(guī)范,后來(lái)的語(yǔ)言像java都支持Unicode文本編碼,當(dāng)然C也有補(bǔ)救的庫(kù).

接下來(lái)辨析兩組設(shè)定:定點(diǎn)數(shù)和浮點(diǎn)數(shù)

計(jì)算機(jī)用二進(jìn)制如何表示小數(shù)呢?要么固定小數(shù)點(diǎn)位置,固定讀取,要么再花空間儲(chǔ)存動(dòng)態(tài)小數(shù)點(diǎn)的位置,這就是頂點(diǎn)和浮點(diǎn)的定義來(lái)源.定點(diǎn)整數(shù)就是整數(shù)啦,分為有符號(hào)和無(wú)符號(hào),而小數(shù)(浮點(diǎn)數(shù))的表示稍微復(fù)雜一點(diǎn)(后述).

布爾大兄弟發(fā)明的布爾代數(shù),邏輯系統(tǒng),增加了四類運(yùn)算:

- 與`And`’&’

- 或`Or`’|’

- 非`Not` ‘'

- 異或`Xor` ‘^’

? ? 異或這個(gè)東西有很多驚奇的用法,比如只用異或可以實(shí)現(xiàn)兩變量交換值(注意!!如果x y數(shù)值相等,則結(jié)果為0);

```c

*x = *x ^ *y;

*y = *x ^ *y;

*x = *x ^ *y;

```

但是記得和邏輯運(yùn)算符區(qū)分開(kāi),位運(yùn)算符都是單符號(hào)運(yùn)算符,邏輯運(yùn)算符都是雙符號(hào)的(除了非是!)

位運(yùn)算還有兩個(gè)小家伙,是左移和右移<<>>,就是將二進(jìn)制數(shù)的小數(shù)點(diǎn)左右移動(dòng),相當(dāng)于原數(shù)據(jù)除以/乘以2.位運(yùn)算比乘法更快,可以作為特別情況下的簡(jiǎn)化.右移存在邏輯右移和算術(shù)右移,算術(shù)右移會(huì)按照最高位數(shù)值復(fù)制補(bǔ)位,而邏輯右移就是補(bǔ)0(大多數(shù)情況下,右移使用邏輯移位).

要注意,如果移位數(shù)量大于目標(biāo)數(shù)據(jù)長(zhǎng)度,編譯器會(huì)先對(duì)移位數(shù)量取模(mod by length of target),用取模結(jié)果再進(jìn)行移位.

C語(yǔ)言中各類數(shù)據(jù)的寬度

![](DraggedImage.png)

### 整型數(shù)

有無(wú)符號(hào)數(shù)唯一的區(qū)別就是符號(hào)位,無(wú)符號(hào)數(shù)全部寬度都用于儲(chǔ)存數(shù)據(jù)內(nèi)容,有符號(hào)數(shù)的最高位被用作符號(hào)位,導(dǎo)致表示范圍減半.

在儲(chǔ)存負(fù)數(shù)時(shí),有符號(hào)數(shù)不是單純的符號(hào)位置1,而是使用補(bǔ)碼,即對(duì)應(yīng)正數(shù)的二進(jìn)制形式反轉(zhuǎn)再+1,就得到對(duì)應(yīng)負(fù)數(shù)的補(bǔ)碼.**補(bǔ)碼使符號(hào)位能與有效值部分一起參加運(yùn)算,從而簡(jiǎn)化運(yùn)算規(guī)則,并使減法運(yùn)算轉(zhuǎn)換為加法運(yùn)算,進(jìn)一步簡(jiǎn)化計(jì)算機(jī)中運(yùn)算器的線路設(shè)計(jì).**

三碼概念辨析:

- 原碼:符號(hào)位+數(shù)值絕對(duì)值

- 反碼:原碼中符號(hào)位不變,其他數(shù)值位和符號(hào)位做異或(即正數(shù)反碼和原碼一樣,負(fù)數(shù)數(shù)值位會(huì)反轉(zhuǎn))

- 補(bǔ)碼:正數(shù)的補(bǔ)碼與其原碼相同(正數(shù)三碼合一),負(fù)數(shù)是反碼的最低位+1.

有無(wú)符號(hào)數(shù)的轉(zhuǎn)換:強(qiáng)制保位轉(zhuǎn)換/軟式保值轉(zhuǎn)換,保位轉(zhuǎn)換就是位模式不變,重新解讀數(shù)值(按目標(biāo)編碼類型的規(guī)則解讀),可能會(huì)有意外副作用:數(shù)值被+/-2^w

**當(dāng)計(jì)算表達(dá)式中既有有符號(hào)數(shù)又有無(wú)符號(hào)數(shù)時(shí),有符號(hào)自動(dòng)強(qiáng)制轉(zhuǎn)化為無(wú)符號(hào)數(shù),這就會(huì)挖很多大坑,像一些宏變量都是unsigned int;另一些循環(huán)里涉及負(fù)數(shù)時(shí),如果遇到無(wú)符號(hào)邊界就可能出現(xiàn)奇怪的循環(huán)現(xiàn)象**

但是可以利用這個(gè)特性去做一些技巧實(shí)現(xiàn),比如向下計(jì)數(shù):

```c

unsigned i; 或者 size_t i;

for (i = cnt-2; i < cnt; i--)

a[i] += a[i+1];

```

**因此除非必要,建議初始化變量時(shí)都用unsigned數(shù)據(jù)**

有的時(shí)候數(shù)據(jù)寬度不夠用了,那就得拓展一下子:符號(hào)拓展.無(wú)符號(hào)數(shù)直接左邊高位填0擴(kuò)展;有符號(hào)數(shù)進(jìn)行拓展,從短整數(shù)類型向長(zhǎng)整數(shù)類型轉(zhuǎn)換時(shí),C自動(dòng)進(jìn)行符號(hào)擴(kuò)展.

有的時(shí)候不小心從長(zhǎng)變短,就得截?cái)嘁幌?疼),那么多出的位直接截?cái)?變量值根據(jù)剩余位數(shù)據(jù)重新解讀,基本就是求模了.

可以再瞅瞅運(yùn)算:

- 加:可能存在溢出,就要丟棄溢出位數(shù)據(jù)(忽略進(jìn)位輸出),有符號(hào)數(shù)還存在正/負(fù)溢出,減法合并到加法.

- 非:這沒(méi)啥說(shuō)的吧

- 乘:依然,溢出就丟棄,可以理解為運(yùn)算完又做了一次取模,想要完整數(shù)據(jù)結(jié)果,需要使用一些特殊的包(_看看寄存器是怎么解決乘法溢出的?_)

- **除**:當(dāng)除數(shù)為2的n次冪,那就右移n位即可;如果不是,就需要舍入除法(實(shí)際結(jié)果為浮點(diǎn)數(shù),舍入后變?yōu)檎麛?shù),避免類型不一致):?

對(duì)于無(wú)符號(hào)數(shù)和有符號(hào)正數(shù),其實(shí)直接移位就可以23333,但是如果是有符號(hào)負(fù)數(shù),需要先加一個(gè)偏移量(2^k-1),然后再右移n位,這樣保證截?cái)嗪笫窍蛄闵崛?即:?

`x / k = ( x + (1<<k)-1 ) >> k`

## 浮點(diǎn)數(shù)

浮點(diǎn)數(shù)這個(gè)東西十分滴有趣,由于小數(shù)點(diǎn)會(huì)自己動(dòng),可以表示非常大的數(shù)或者非常接近零的數(shù),但是本質(zhì)上還是2為基的一種表示方式,所以很多小數(shù)只能通過(guò)多位逼近表示其近似值,像0.27這種數(shù).

IEEE(Institute of Electrical and Electronics Engineers)電子和電氣工程師協(xié)會(huì)統(tǒng)一了規(guī)范,設(shè)置了IEEE 754這樣的浮點(diǎn)規(guī)范:(有關(guān)IEEE 754的詳細(xì)介紹 [點(diǎn)擊鏈接](http://c.biancheng.net/view/314.html))

一個(gè)浮點(diǎn)數(shù)由符號(hào)(sign),尾數(shù)(mantissa/fraction/significand),基(base),階(exponent)和一個(gè)點(diǎn)構(gòu)成,對(duì)于計(jì)算機(jī)的浮點(diǎn)小數(shù),可以用2位基的不科學(xué)計(jì)數(shù)法表示:Mx2^E.

在32/64位浮點(diǎn)數(shù)儲(chǔ)存的格式不同,float浮點(diǎn)數(shù)中,第0位是符號(hào)位,1-8位是階碼位,9-31是尾數(shù)位;在double中,0是負(fù)號(hào),1-11是階碼,12-63是尾數(shù)

但是你想得太簡(jiǎn)單了!(我也天真了),他們分了規(guī)格化數(shù)和非規(guī)格化數(shù),咱摳一摳吧:

- **規(guī)格化數(shù)**:浮點(diǎn)數(shù)階碼位不全為0/1時(shí)為規(guī)格化數(shù)范圍?

但是階碼采用偏置值編碼,exponent=E+Bias,其中Bias的值在32/6位浮點(diǎn)數(shù)中分別為127/1023.?

尾數(shù)編碼時(shí),默認(rèn)第一位為1(二進(jìn)制),這樣節(jié)省了一位精度,只需要表示M中小數(shù)點(diǎn)后面的數(shù)據(jù)即可,當(dāng)frac段為全0時(shí),這個(gè)M就是1(最小的規(guī)格化數(shù)),當(dāng)frac全為1時(shí),M趨近于2,是最大值.

- **非規(guī)格化數(shù)**:這個(gè)老哥可以表示規(guī)格化數(shù)范圍外的數(shù)據(jù),很有用.?

exp=000…000時(shí),**E=1-Bias**,尾數(shù)里默認(rèn)第一位是0,這樣就能表示0附近的數(shù)(lim-\>0)了,此時(shí)又會(huì)出來(lái)一對(duì)正負(fù)0.?

exp=111…111時(shí),當(dāng)frac=0 就可以表示正負(fù)無(wú)窮(除零錯(cuò)誤),如果frac!=0,那輸出的就是NaN了

![](DraggedImage-1.png)

數(shù)說(shuō)完了,那咋計(jì)算呢?浮點(diǎn)數(shù)運(yùn)算有個(gè)基本思想,就是先算精確值,然后根據(jù)輸出變量類型進(jìn)行相應(yīng)轉(zhuǎn)化,是舍入還是溢出了etc.

說(shuō)到舍入呢,有四種舍入方法,最簡(jiǎn)單的倆就是向上舍入和向下舍入,不管小數(shù)位是啥直接進(jìn)位或者舍去,另外還有向零舍入和向偶數(shù)舍入.最后這個(gè)**向偶數(shù)舍入**是重點(diǎn),也是默認(rèn)舍入模式.

**偶數(shù)舍入**:當(dāng)小數(shù)不等于中間值時(shí)就采用向上或者向下舍入,等于中間值的時(shí)候判斷哪邊舍入之后變成偶數(shù)形式(小數(shù)最后一位為偶數(shù),二進(jìn)制時(shí)舍入位右側(cè)全為0)即可.

回到計(jì)算,我們只需要關(guān)注乘法和加法就可以,其他的運(yùn)算大同小異.

- **乘法**:階碼相加尾數(shù)相乘,這個(gè)不用多說(shuō),數(shù)學(xué)知識(shí).當(dāng)尾數(shù)相乘后\>2了,那就進(jìn)個(gè)位,右移一下,E+1就完事了;但是也有可能溢出,乘積太大了唄,那就會(huì)報(bào)錯(cuò)了.運(yùn)算最后肯定加一步舍入,這個(gè)前面剛說(shuō).

- **加法**:首先得對(duì)齊小數(shù)點(diǎn)再相加,結(jié)果的階碼等于加數(shù)里最大的E(對(duì)齊小數(shù)點(diǎn)了嘛),進(jìn)位溢出舍入的操作和乘法都相似.

前面說(shuō)的都是浮點(diǎn)數(shù)運(yùn)算的通用規(guī)則和設(shè)定,在C語(yǔ)言中還有一些注意事項(xiàng):

1. int轉(zhuǎn)float,不會(huì)溢出,但是可能舍入

2. 低精度轉(zhuǎn)高精度,不會(huì)丟數(shù)據(jù)(廢話),反過(guò)來(lái)可能造成溢出/舍入,丟數(shù)據(jù)(還是廢話)

3. 從浮點(diǎn)直接轉(zhuǎn)int的話,就咔嚓一下截?cái)嗔?/p>

## 內(nèi)存 指針 字符串

內(nèi)存就是個(gè)超大數(shù)組,線性存著一大堆數(shù)據(jù),內(nèi)存地址就是數(shù)組的索引,指針就是索引的值.從8章可知,其實(shí)每個(gè)進(jìn)程都有屬于自己獨(dú)占的內(nèi)存空間,高度抽象的進(jìn)程管理方式.

字長(zhǎng):地址數(shù)據(jù)寬度,如果是32位地址,那內(nèi)存最大4G(32位系統(tǒng)內(nèi)存上限),64位地址,那內(nèi)存上限老大了(懶得算),計(jì)算機(jī)目前使用的是面向”字”的內(nèi)存組織管理,每個(gè)字占4/8字節(jié)

字節(jié)排列順序(從小到大/從大到小)就分為小端法和大端法,這個(gè)隨操作系統(tǒng)變化,可以利用指針/共用體輸出一個(gè)變量的低位/高位數(shù)據(jù)值來(lái)判斷.

字符串就是ASCII碼表示咯!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末督弓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子乒验,更是在濱河造成了極大的恐慌愚隧,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锻全,死亡現(xiàn)場(chǎng)離奇詭異奸攻,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)虱痕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門睹耐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人部翘,你說(shuō)我怎么就攤上這事硝训。” “怎么了新思?”我有些...
    開(kāi)封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵窖梁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我夹囚,道長(zhǎng)纵刘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任荸哟,我火速辦了婚禮假哎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鞍历。我一直安慰自己舵抹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布劣砍。 她就那樣靜靜地躺著惧蛹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刑枝。 梳的紋絲不亂的頭發(fā)上香嗓,一...
    開(kāi)封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音装畅,去河邊找鬼靠娱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛洁灵,可吹牛的內(nèi)容都是我干的饱岸。 我是一名探鬼主播掺出,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼苫费!你這毒婦竟也來(lái)了汤锨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤百框,失蹤者是張志新(化名)和其女友劉穎闲礼,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铐维,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柬泽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫁蛇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锨并。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖睬棚,靈堂內(nèi)的尸體忽然破棺而出第煮,到底是詐尸還是另有隱情,我是刑警寧澤抑党,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布包警,位于F島的核電站,受9級(jí)特大地震影響底靠,放射性物質(zhì)發(fā)生泄漏害晦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一暑中、第九天 我趴在偏房一處隱蔽的房頂上張望壹瘟。 院中可真熱鬧,春花似錦痒芝、人聲如沸俐筋。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至笆呆,卻和暖如春请琳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赠幕。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工俄精, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人榕堰。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓竖慧,卻偏偏與公主長(zhǎng)得像嫌套,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子圾旨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容