資訊的儲存及整數表示
深入理解計算機系統(第三版)第二章前半部分讀書筆記
字資料大小
前面已經提到過資訊=位+上下文
,但是基本上的計算機都沒有將位作為最小的可定址單位,而是將位元組作為了最小的可定址單位,記憶體就是一個非常大的位元組陣列,它的的每個位元組都由一個唯一的數字來標識(這個數字是不需要存的),所有可能的地址集合就是虛擬地址空間。
我們常說的 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 即可,而需要注意的是從大往小轉,這會不可避免的截斷位,造成資訊的丟失,所以千萬不要這麼幹。
原文連結:https://mp.weixin.qq.com/s/heir0p_0v916ifbapzKAIw
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555494/viewspace-2218232/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 數值資訊的機器級儲存
- Netapp儲存日常檢查及資訊收集APP
- mysql儲存地理資訊的方法MySql
- 教你用一個整數儲存每月打卡記錄
- 使用執行緒本地變數儲存會員資訊執行緒變數
- 修改docker的預設儲存位置及映象儲存位置Docker
- 儲存管理(一):openfiler介紹及儲存理解
- 數字時代,如何搞定資訊儲存這件麻煩事?
- 區塊鏈資訊儲存是如何實現安全儲存區塊鏈
- Laravel 自定義配置資訊的儲存方式Laravel
- 系統統計資訊的儲存位置
- .C++整數的N進位制字串表示C++字串
- Activity Monitor log儲存時間調整
- 儲存過程——公用表表示式(CTE)儲存過程
- MySQL 中 整數型別的儲存和範圍計算過程詳解MySql型別
- iscsi 掛載網路儲存及儲存訪問
- Dart型別變數-表示資訊Dart型別變數
- (十二)本地儲存及同步
- STM32 記憶體分配解析及變數的儲存位置記憶體變數
- Java中的Properties類儲存丟失資訊?!Java
- 使用SpringBoot JPA進行自定義的儲存及批量儲存Spring Boot
- LMT下表儲存引數的使用
- mysql儲存過程的引數MySql儲存過程
- 企業如何做好資訊儲存
- 穀粒商城day61-商品服務-API-新增商品-儲存SPU基本資訊+儲存SKU基本資訊+呼叫遠端服務儲存優惠等資訊API
- 造數儲存過程儲存過程
- 使用SpringBoot-JPA進行自定義的儲存及批量儲存Spring Boot
- Android資料儲存之SharedPreferences及如何安全儲存Android
- NFS儲存服務及部署NFS
- 【儲存】GPFS簡介及搭建
- MySQL 儲存函式及呼叫MySql儲存函式
- 儲存過程獲取表被引用的資訊儲存過程
- 列印QObject 對應的QMetaObject中儲存的方法資訊Object
- MySQL:Innodb中數字的儲存方式MySql
- 簡單的造數儲存過程儲存過程
- 數值在Oracle的內部儲存Oracle
- 儲存過程中巢狀儲存過程的變數執行方式儲存過程巢狀變數
- redis儲存使用者登入資訊Redis