資訊的儲存及整數表示

2021-08-29 18:49:35 字數 2266 閱讀 8056

深入理解計算機系統(第三版)第二章前半部分讀書筆記

字資料大小

前面已經提到過資訊=位+上下文,但是基本上的計算機都沒有將位作為最小的可定址單位,而是將位元組作為了最小的可定址單位,記憶體就是乙個非常大的位元組陣列,它的的每個位元組都由乙個唯一的數字來標識(這個數字是不需要存的),所有可能的位址集合就是虛擬位址空間。

我們常說的 32 位、64 位指的是一台計算機的字長,用於指明指標資料的的標稱大小。有的面試官在面試的時候會問這樣乙個問題:在 c/c++ 中指標的大小是多少?如果你一下就回答出來時多少個位元組了,那基本上不必再問了,因為乙個指標的大小取決於計算機的字長,所以應該分 32 位機還是 64 位機的情況。

字長還會決定乙個極為重要的系統引數——虛擬位址空間。比如現在有乙個 32 位機,每一位可以取值 1 或 總共 32 位,能組合的出局就有 232 個,所以它能訪問 232 個位址,其大小也就是 4g,因此你如果給 32 位機裝上 8g 的記憶體條,是起不了多大作用的。

我們平時所說的 32 位程式和 64 位程式並不是指機器的字長,它們的區別在於程式時如何編譯的,而不是其執行的機器型別,高版本都應該做到向後相容,所以 32 位程式一般都能執行在 64 位機器上,而 64 位程式時不能執行在 32 位機上面的。下面兩種偽指令就分別用於編譯 32 位程式和 64 位程式。

gcc -m32 prog.c

gcc -m64 prog.c

c 語言在 32 位機和 64 位機上所表現的差別在於long資料型別,一般在 32 位機上是 4 個位元組,而在 64 位機上是 8 個位元組,而作為程式設計師要力圖程式能在不同的機器上進行編譯執行,要做到這一點就需要保證程式對不同資料型別的確切大小不敏感。

曾經某運營商的乙個基站版本因為資料範圍的不同而造成了巨大的損失,在程式設計環境中使用的是 32 位機,而基站所使用的處理器沒有 32 位,最後表現的效果就是大概每隔 40 天,基站就自動復位了。定位到這個問題都花費了巨大的財力和人力資源。

定址及位元組順序

上文已經提到,有很多的物件實際上不止占用乙個位元組,而是占用了多個位元組,此時就涉及到如何排列這些位元組了,以及如何儲存這些位元組。以11001100 11001100為例,它占用了兩個位元組,我們可以選擇將這兩個位元組放在連續的記憶體中,也可以將兩個位元組分開放在不連續的記憶體中;另外我們可以將左邊的位元組當做起始位置,也可以將右邊的位元組當做起始位置(更專業的稱為大端法和小端法)。

對於位元組的排列,到底是用大端法還是小端法,沒有技術上的爭論,只有社會政治論題的爭論,而且機器它對程式設計師是完全不可見的。幾乎所有的機器都將多位元組物件儲存為連續的位元組序列,所使用位元組中最小的位址作為物件的位址。

那麼什麼時候需要注意位元組的順序規則呢,那就是編寫網路應用程式的時候,試想你傳輸的資料是用大端法表示的,而使用者的計算機採用的是小端法,那還會有使用者使用你的產品嗎。所以編寫網路程式時需要遵循已經建立的關於位元組順序的規則。

整數表示

程式設計師對二進位制不會不知道,比如11111111表示的是 255(不考慮補碼),很容易就能轉換為我們所熟悉的 10 進製資料。這種方式我們預設它是無符號數,如果要加入有符號數就開始變得有趣了。

幾乎所有的計算機都是採用有補碼來表示有符號整數的,它與無符號整數的區別在於最高位被解釋為負權,舉個例子:將1111看做補碼的話,它的值就為:-23 + 22 + 21 + 20 = -1。

在程式中不可避免的會使用強制型別轉換,c 語言中強制型別轉換並沒有改變資料的位值,只是改變了解釋這些位的方式。比如將無符號數(unsigned) 53191 轉換為有符號數的結果為 -12345,它們的位值是完全沒有相同的。

最容易入坑的地方是,對兩個不同型別的資料進行運算時,c 語言將會隱式的將有符號數轉換為無符號數,所以就有下面這樣乙個神奇的結果。

// u 代表無符號數

-1 < 0u

// 結果為 0

// 因為 -1 的補碼表示為:11...11

// 轉換為無符號數後就是範圍內最大的數

如果需要擴充套件乙個數的位表示,那麼放心的擴充套件就好了,小的資料型別都能安全的向大的資料型別轉換,補碼表示的數會在前面補上符號位,原碼表示的直接在前面補上 0 即可,而需要注意的是從大往小轉,這會不可避免的截斷位,造成資訊的丟失,所以千萬不要這麼幹。

羅馬數表示整數

羅馬數字共有七個,即 i 1 v 5 x 10 l 50 c 100 d 500 m 1000 按照下面三條規則可以表示任意正整數。重複數次 乙個羅馬數字重複幾次,就表示這個數的幾倍。右加左減 在乙個較大的羅馬數字的右邊記上乙個較小的羅馬數字,表示大數字加小數字。在乙個較大的數字的左邊記上乙個較小的...

整數表示問題。

我們知道,如果x,y互素時ax by可以表示任意整數 其中a,b為整數 如果設定條件x,y 0,並且ax by 0時,求能表示的整數集中連續的整數最小的是多少?例如輸入x 3,y 4.整數集為0,3,4,6,7,8,9 則輸出6 輸入1行x和y,輸出一行表示最小整數 其中x,y為32位整數且互素。現...

整數表示法

整數表示法 題目詳情 我們知道,如果x,y互素時ax by可以表示任意整數 其中a,b為整數 如果設定條件x,y 0,並且ax by 0時,求能表示的整數集中連續的整數最小的是多少?例如輸入x 3,y 4.整數集為0,3,4,6,7,8,9 則輸出6 輸入1行x和y,輸出一行表示最小整數 其中x,y...