類型的本質:對變量、類型、指針的理解


核心觀點:類型約定了對數據的解釋方式

信息和數據

來自 wikipedia 的定義

https://en.wikipedia.org/wiki/Information

https://en.wikipedia.org/wiki/Data

wikipedia 上的定義真的是太晦澀了

在我的理解中,數據就是不帶有任何屬性的數字。例如一個數字1,就是一個單純的數據。

僅通過一個數字 1,你是無法得到任何信息的,因為你不知道這個1到底代表什么意思。只有結合具體的語境,你才能從中獲得有用的信息。

例如1本書、1個人、1頭豬等等

上面的書、人、豬實際上就是對數據的解釋方式。他們分別將 1 解釋為書的數量、人的數量、豬的數量。

因此為了獲取信息,除了知道數據本身外,你還得需要知道對數據的解釋方式。

所以,信息 = 數據 + 數據的解釋方式

想一想諜戰片子里面的電報機,電報機所發送的實際上是一些長短不一的摩爾斯電碼,這些摩爾斯電碼就是數據,外部人員不知道這些電碼代表的是啥,但是專業的諜報人員對其翻譯后,就可以從其中獲取到有用的信息。這里的翻譯實際上就是在對數據進行解釋。翻譯工作可能是依靠一個密碼本來進行的,密碼本上約定了數據的解釋方式。

例子
l i v e

這四個字母,如果用從左至右的方式來解釋,將是 live,如果用從右至左的方式來解釋,將是 evil。

1 0 1 1

這四個數字,如果每兩個一組進行解釋,將會得到

10 11

如果每四個一組進行解釋,將會得到

1011

同樣的數據,使用不同的解釋方式,就能得到不一樣的信息。

類型約定了對數據的解釋方式

c 語言中有如下一些基礎數據類型,摘自https://www.runoob.com/cprogramming/c-data-types.html

整數類型

類型 存儲大小 值范圍
char 1 字節 -128 到 127 或 0 到 255
unsigned char 1 字節 0 到 255
signed char 1 字節 -128 到 127
int 2 或 4 字節 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 2 或 4 字節 0 到 65,535 或 0 到 4,294,967,295
short 2 字節 -32,768 到 32,767
unsigned short 2 字節 0 到 65,535
long 4 字節 -2,147,483,648 到 2,147,483,647
unsigned long 4 字節 0 到 4,294,967,295

浮點類型

類型 存儲大小 值范圍 精度
float 4 字節 1.2E-38 到 3.4E+38 6 位小數
double 8 字節 2.3E-308 到 1.7E+308 15 位小數
long double 16 字節 3.4E-4932 到 1.1E+4932 19 位小數

再回顧一下我的核心觀點:類型約定了對數據的解釋方式

在這里我就取 char 類型和 short 類型來解釋。char 類型的大小是 1 字節,short 類型的大小是 2 字節。一字節 byte 等於 8 bit,一個 bit 就是一個二進制位,值為 0 或 1。實際上 char 約定了以 8 個 bit 為一組來解釋,而 short 則約束了以 16 個 bit 為一組來解釋。

現在有一個 16 個 bit 大小的空間,空間里的內容為:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1

如果用 char (每 8 個 bit 為一組)來解釋,則可以解釋為兩個 char,char0 = 00000000 = 0,char1 = 00000001 = 1。

如果用 short (每 16 個 bit 為一組)來解釋,則可以解釋為 1 個 short,short0 = 0000000000000001 = 1。

變量(variable) = 地址(address) + 類型(type)

一個變量由兩個要素組成,分別是變量的地址,以及變量的類型。

address 確定了存放變量的字面值的空間位置

type 約定了如何解釋這段空間

在 c 語言中,初始化一個變量的方式是:

char a = 1;

例如在這里,

  • 變量 a 的 address 是 &a
  • 類型是 char,它決定了將會以 8 個 bit 為單位解釋 address 中的內容
  • a 的字面值是 1,字面值是通過 address 和 char 通過得到的

在 address 處存放了數據本體,利用 type 來解釋數據,最終得到字面值這個信息。

對變量的訪問是通過訪問該變量的地址來完成的

在 c 語言中,對於變量的訪問實際上都是通過訪問該變量的地址來完成的。但是只有地址還不夠,如何解釋這篇地址的內容,是以 8 個 bit 為單位亦或者是以 16 個 bit 為單位,這就需要用到類型了。

變量在初始化時,會被分配一個地址。這個地址就是變量的家,變量的地址是不會發生改變的,它一輩子只會有一個家,不會搬家。

變量的初始化
char c = 1;

在這行代碼里,實際上會有如下兩步操作:

  1. 為變量 c 分配一個空間,這個空間就是 c 的家,假設 c 住在地球一號村,二號樓0號房間吧,就用 0x120 來表示 c 的地址吧。

  2. 將 0x120 ~ 0x128 這 8 個 bit 的空間里的內容初始化為 1(其實 c 里面地址的單位是 1 個 byte,而非 bit),變成下面這個樣子:

    image

    為何是 8 個 bit 而不是其他數字的 bit?這是 c 的類型所決定的,因為類型是 char,所以是 8 個 bit。

對 c 的修改
c = 2

實際上還是分為兩步:

  1. 第一步還是先得到 c 的地址,之前說過變量的地址是不會發送改變的,因此這里變量 c 的地址也就是 0x120

  2. 將 0x120 ~ 0x128 這 8 個 bit 的空間里的內容初始化為 2,變成了下面這樣:

    image

對 c 的訪問
char i = c;
  1. 得到 c 的地址 0x120
  2. 對 0x120 ~ 0x128 這 8 個 bit 大小的空間進行解釋。類型約定了對數據的解釋方式,而這里的類型是 char,所以用 8 個 bit 的方式來解釋。
  3. 對 i 的操作也是類似的...

指針

指針變量本質和普通的變量沒有太大區別,依舊由值和類型組成,同樣也會被分配一個地址。

但是它相比普通變量多了一個 * (dereference) 操作。dereference 是指針變量所特有的操作,普通的變量是無法進行 dereference 操作的,否則會發生編譯錯誤。

定義一個指針變量
char* p = 0x120;

p 的值是 0x120 ,p 的類型是 char* (指向 char 類型的指針)。

char* = char + *
* 表明這個變量是一個指針,因此有 dereference 能力
char 約定了在 dereference 時,它將會以 8 個 bit為 單位來解釋
deference

通過 dereference ,可以對地址中的內容進行操作。

*p = 1

這句代碼將會把 0x120 ~ 0x128 這 8 個 bit 的空間里的內容置為 1。

image

對指針變量的修改
p = 2

與上面所說的變量的修改過程是一樣。

一些具體的例子

基本原則
  1. 變量 = address + type
  2. 變量會被分配一個地址,且這個地址是固定的
  3. 對變量的訪問是通過訪問變量的地址來完成的,變量的類型約定了對地址中內容的解釋方式
例子1:通過指針來修改變量的值
char c = 1;			// 為 c 分配地址,假設 c 的地址是 0x120,c 的值是 1,0x120 ~ 0x128 這 8 個 bit 的內容是 1
char* pc = &c;		// pc 是一個指針,它的值是 c 的地址,則 pc 的值是 0x120
*pc = 2;			// dereference 操作,將 0x120 ~ 0x128 這 8 個 bit 的內容設置為 2
printf("%d",c);		// 取 0x120 ~ 0x128 這 8 個 bit 的內容進行解釋,得到 2,因此輸出 2
例子2:指向指針的指針
char* pc = null;	// 為 pc 分配地址,假設 pc 的地址是 0x1200,pc 的值是 0,0x1200 ~ 0x1220 這 32 個 bit 的內容是 0(在 32 為環境下,指針的大小是 32 bit)
char** ppc = &pc;  // ppc 的值為 0x1200
char c = 1;		   // 為 c 分配地址,假設 c 的地址是 0x120,c 的值是 1,0x120 ~ 0x128 這 8 個 bit 的內容是 1
*ppc = &c;		   // 將 0x1200 ~ 0x1220 這 32 個 bit(char*) 的內容設置為 0x120,此時 pc 的值為 0x120 了
*pc = 2;		   // 取 0x120 ~ 0x128 這 8 個 bit(char) 的內容設置為 2, 此時 c 的值變成 2 了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM