C語言雜談:指標與陣列 (上)

川山甲發表於2015-04-28

 思維導圖

 

介紹

1> 指標定義:指標是儲存變數地址的變數。

2> 本文重點
>> 指標與陣列之間的關係
>> 操縱指標的規則

3> 指標優點
>> 表達某個計算的唯一途徑
>> 程式碼更高效,更緊湊

4> 指標缺點:難以理解,但是用好了,程式碼會非常清晰。

5> 將指標、陣列和地址的算術運算整合在一起是C語言的一大優點。

指標與地址

1> 記憶體組織方式

 

 (1) 記憶體是一個個單元組成的,每一個記憶體單元中存放一個位元組(8位)的二進位制資訊。
 (2) 機器中的記憶體單元是有序排列的。
 (3) 機器給各個記憶體單元規定不同地址來管理記憶體。這樣,CPU通過地址來識別不同的記憶體單元,正確的對記憶體單元進行操作。
2> 指標與變數的關係(P:是指標變數,C:記憶體物件)

>>> P:儲存C:中的單元首地址——這裡的地址不是實體地址,而是經過地址對映後的虛擬地址,即邏輯地址。

>>> P:為指向C:的指標

3>理解指標

>>> 指標佔用的記憶體空間大小: 32位系統佔用4byte,64為8byte。

機器配置:

列印指標大小:

>>> 指標就是地址——我們可以把指標認為是用來存放地址的資料型別。不能把指標簡簡單單的當成一個整型數,雖然地址的值是一個整型資料。

>>> 指標是有型別的,但是這個型別不是給指標分配記憶體的,而是用來定址的。

 

指標與函式引數

1.普通引數:C語言通過傳值方式將值傳遞給被呼叫函式。

>> 會把變數的值複製一份給被呼叫函式。
>> 複製:會把變數的值賦值給一個新的變數(引數)——變數和新的變數必須有相同的儲存容量。
>> 被呼叫函式並不能修改主調程式中的變數值,因為被呼叫函式使用的是一個複製過來的記憶體單元。

2.指標引數: 本質上跟普通引數傳遞是相同的,也進行了變數複製,但是傳過去的值是地址。 被呼叫函式通過地址能夠訪問和修改主調程式中變數的值。

3.引數在記憶體消耗

普通引數:取決於申明型別。char:1個位元組;short:2個位元組;long:8個位元組
指標引數:指標變數裡儲存的是地址(一般是4個位元組——32位),永遠是一個固定長度,不管是什麼型別的指標。——除非處理器變化不是32位。

4.double *dp, atof(char *) 這裡的dp是指標變數,而atof是函式

 

指標與陣列

1.指標運算元組快於下標運算元組

2.陣列的空間分配.如int a[10];——會在空間分配出40個相鄰的記憶體單元來(10*4)。

 

3.指標運算元組

int *pa;
pa = &a[0];

 

4.指標移動

int *pa;
int a[10];
pa = &a[0];

pa+1將指向下一個元素a[1]:

>> 記憶體中的變化:”指標加1″會根據指標指定的型別int移動4個記憶體單元,其實本身並沒有移動,只是pa+1等於第5個記憶體單元地址——“指標加1”中的1的大小是取決於pa的型別int的,指標型別決定指標跨記憶體單元的步長。

>> pa+1 等於是指向第5個記憶體單元——a[1]的第一個記憶體單元。

5.規則:

>> &a[i]和a+i含義相同,相互使用。a+i是a之後第i個元素地址。
>> 陣列名代表陣列第一個元素的地址。

 

地址運算子

1. 指標初始化:0或表示地址的表示式。

2. “指標加1”中的“1”的大小根據資料型別的長度按比例縮放。如果int型別佔4個位元組的儲存空間,對應的1按4倍計算。

 

驗證:

>>> 若指向char型別的指標p的記憶體地址是0x000000,那麼p+1後的地址是0x000001。

驗證過程如下:

執行結果:

 

>>> 若指向int 型別的指標p的記憶體地址是0x000000,那麼p+1後的地址是0x000004。

執行結果:

3.指向不同陣列的元素的指標之間的算術或比較運算都沒有定義。

4.指標相減:如果p和q指向相同陣列中的元素,且p<q,那麼q-p+1就是p和q之間的元素(包括p和q)

程式碼驗證:

執行結果:

流程變化:q-p=16 => 16/4=4 (按照int型所佔記憶體單元等比例縮放) => 4 + 1 = 5;

 

總結

這次寫關於c語言方面指標,是因為這兩天看php核心檔案的時候,由於C方面的欠缺,所以看著很吃力。所以想再複習下C語言。

為什麼從指標入手呢?可能是因為指標在C語言中是比較難的。所以先把最難的啃下來。

本來是想一次性寫完,可是指標這方面內容太多,所以決定分幾批寫。

我在C語言方面還是很薄弱,如果文章中有錯誤,希望高手們指點下。

參考文獻:《C程式設計語言》

相關文章