1. 程式人生 > 實用技巧 >c語言的指標

c語言的指標

本文轉載:http://c.biancheng.net/view/1990.html

計算機中所有的資料都必須放在記憶體中,不同型別的資料佔用的位元組數不一樣,例如 int 佔用 4 個位元組,char 佔用 1 個位元組。為了正確地訪問這些資料,必須為每個位元組都編上號碼,就像門牌號、身份證號一樣,每個位元組的編號是唯一的,根據編號可以準確地找到某個位元組。

下圖是 4G 記憶體中每個位元組的編號(以十六進位制表示):


我們將記憶體中位元組的編號稱為地址(Address)或指標(Pointer)。地址從 0 開始依次增加,對於 32 位環境,程式能夠使用的記憶體為 4GB,最小的地址為 0,最大的地址為 0XFFFFFFFF。

下面的程式碼演示瞭如何輸出一個地址:

  1. #include <stdio.h>
  2. int main(){
  3. int a = 100;
  4. char str[20] = "c.biancheng.net";
  5. printf("%#X, %#X\n", &a, str);
  6. return 0;
  7. }

執行結果:
0X28FF3C, 0X28FF10

%#X表示以十六進位制形式輸出,並附帶字首0X。a 是一個變數,用來存放整數,需要在前面加&來獲得它的地址;str 本身就表示字串的首地址,不需要加&

C語言中有一個控制符%p,專門用來以十六進位制形式輸出地址,不過 %p 的輸出格式並不統一,有的編譯器帶0x
字首,有的不帶,所以此處我們並沒有採用。

一切都是地址

C語言用變數來儲存資料,用函式來定義一段可以重複使用的程式碼,它們最終都要放到記憶體中才能供 CPU 使用。

資料和程式碼都以二進位制的形式儲存在記憶體中,計算機無法從格式上區分某塊記憶體到底儲存的是資料還是程式碼。當程式被載入到記憶體後,作業系統會給不同的記憶體塊指定不同的許可權,擁有讀取和執行許可權的記憶體塊就是程式碼,而擁有讀取和寫入許可權(也可能只有讀取許可權)的記憶體塊就是資料。

CPU 只能通過地址來取得記憶體中的程式碼和資料,程式在執行過程中會告知 CPU 要執行的程式碼以及要讀寫的資料的地址。如果程式不小心出錯,或者開發者有意為之,在 CPU 要寫入資料時給它一個程式碼區域的地址,就會發生記憶體訪問錯誤。這種記憶體訪問錯誤會被硬體和作業系統攔截,強制程式崩潰,程式設計師沒有挽救的機會。

CPU 訪問記憶體時需要的是地址,而不是變數名和函式名!變數名和函式名只是地址的一種助記符,當原始檔被編譯和連結成可執行程式後,它們都會被替換成地址。編譯和連結過程的一項重要任務就是找到這些名稱所對應的地址。



假設變數 a、b、c 在記憶體中的地址分別是 0X1000、0X2000、0X3000,那麼加法運算c = a + b;將會被轉換成類似下面的形式:

0X3000 = (0X1000) + (0X2000);

( )表示取值操作,整個表示式的意思是,取出地址 0X1000 和 0X2000 上的值,將它們相加,把相加的結果賦值給地址為 0X3000 的記憶體

變數名和函式名為我們提供了方便,讓我們在編寫程式碼的過程中可以使用易於閱讀和理解的英文字串,不用直接面對二進位制地址,那場景簡直讓人崩潰。

需要注意的是,雖然變數名、函式名、字串名和陣列名在本質上是一樣的,它們都是地址的助記符,但在編寫程式碼的過程中,我們認為變數名錶示的是資料本身,而函式名、字串名和陣列名錶示的是程式碼塊或資料塊的首地址。

關於程式記憶體、編譯連結、可執行檔案的結構以及如何找到名稱對應的地址,我們將在《C語言記憶體精講》和《C語言多檔案程式設計》專題中深入探討。