對c指標的理解解析

2021-08-08 22:03:29 字數 2589 閱讀 9887

計算機中所有的資料都必須放在記憶體中,不同型別的資料占用的位元組數不一樣,例如 int 占用4個位元組,char 占用1個位元組。

為了正確地訪問這些資料,必須為每個位元組都編上號碼,就像門牌號、身份證號一樣,每個位元組的編號是唯一的,根據編號

可以準確地找到某個位元組。

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

我們將記憶體中位元組的編號稱為位址(address)或指標(pointer)。

位址從 0 開始依次增加,對於 32 位環境,程式能夠使用的記憶體為 4gb,最小的位址為 0,

最大的位址為 0xffffffff。

str 本身就表示字串的首位址,不需要加&。

一切都是位址c語言用變數來儲存資料,用函式來定義一段可以重複使用的**,它們最終都要放到記憶體中才能供 cpu 使用。

資料和**都以二進位制的形式儲存在記憶體中,計算機無法從格式上區分某塊記憶體到底儲存的是資料還是**。當程式被載入到記憶體後,

作業系統會給不同的記憶體塊指定不同的許可權,擁有讀取和執行許可權的記憶體塊就是**,而擁有讀取和寫入許可權(也可能只有讀取許可權)

的記憶體塊就是資料。

cpu 只能通過位址來取得記憶體中的**和資料,程式在執行過程中會告知 cpu 要執行的**以及要讀寫的資料的位址。

如果程式不小心出錯,或者開發者有意為之,在 cpu 要寫入資料時給它乙個**區域的位址,就會發生記憶體訪問錯誤。

這種記憶體訪問錯誤會被硬體和作業系統攔截,強制程式崩潰,程式設計師沒有挽救的機會。

cpu 訪問記憶體時需要的是位址,而不是變數名和函式名!變數名和函式名只是位址的一種助記符,當原始檔被編譯和鏈結成可執行程式後,

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

0x3000 = (0x1000) + (0x2000);( )表示取值操作,整個表示式的意思是,取出位址 0x1000 和 0x2000 上的值,將它們相加,

理解的英文本串,不用直接面對二進位制位址,那場景簡直讓人崩潰。

需要注意的是,雖然變數名、函式名、字串名和陣列名在本質上是一樣的,它們都是位址的助記符,但在編寫**的過程中,

我們認為變數名表示的是資料本身,而函式名、字串名和陣列名表示的是**塊或資料塊的首位址。

c語言指標變數的運算

指標變數儲存的是位址,本質上是乙個整數,可以進行部分運算,例如加法、減法、比較等,請看下面的**:

1.#include

3.int main()

else

22.return 0;

}執行結果:

&a=0x28ff44, &b=0x28ff30, &c=0x28ff2bpa=0x28ff44, pb=0x28ff30, pc=0x28ff2bpa=0x28ff48, pb=0x28ff38, 

pc=0x28ff2cpa=0x28ff40, pb=0x28ff28, pc=0x28ff2a2686784

從運算結果可以看出:pa、pb、pc 每次加 1,它們的位址分別增加 4、8、1,正好是 int、double、char 型別的長度;減 2 時,

位址分別減少 8、16、2,正好是 int、double、char 型別長度的 2 倍。這很奇怪,指標變數加減運算的結果跟資料型別的長度有關,

而不是簡單地加 1 或減 1,這是為什麼呢?以 a 和 pa 為例,a 的型別為 int,占用 4 個位元組,pa 是指向 a 的指標,如下圖所示:

剛開始的時候,pa 指向 a 的開頭,通過 *pa 讀取資料時,從 pa 指向的位置向後移動 4 個位元組,把這 4 個位元組的內容作為要獲取的資料,

這 4 個位元組也正好是變數 a 占用的記憶體。

這個時候 pa 指向整數 a 的中間,*pa 使用的是紅色虛線畫出的 4 個位元組,其中前 3 個是變數 a 的,

後面 1 個是其它資料的,把它們「攪和」在一起顯然沒有實際的意義,取得的資料也會非常怪異。

如果pa++;使得位址加 4 的話,正好能夠完全跳過整數 a,指向它後面的記憶體,如下圖所示:

我們知道,陣列中的所有元素在記憶體中是連續排列的,如果乙個指標指向了陣列中的某個元素,那麼加 1 就表示指向下乙個元素,

減 1 就表示指向上乙個元素,這樣指標的加減運算就具有了現實的意義,我們將在《c語言和陣列》一節中深入**。

不過c語言並沒有規定變數的儲存方式,如果連續定義多個變數,它們有可能是挨著的,也有可能是分散的,這取決於變數的型別、

編譯器的實現以及具體的編譯模式,所以對於指向普通變數的指標,我們往往不進行加減運算,雖然編譯器並不會報錯,但這樣做沒有意義

,因為不知道它後面指向的是什麼資料。

指標變數除了可以參與加減運算,還可以參與比較運算。當對指標變數進行比較運算時,比較的是指標變數本身的值,

也就是資料的位址。如果位址相等,那麼兩個指標就指向同乙份資料,否則就指向不同的資料。

上面的**(第乙個例子)在比較 pa 和 paa 的值時,pa 已經指向了 a 的上乙份資料,所以它們不相等。而 a 的上乙份資料又不知道是什麼,所以會導致 printf() 輸出乙個沒有意義的數,這正好印證了上面的觀點,不要對指向普通變數的指標進行加減運算。

另外需要說明的是,不能對指標變數進行乘法、除法、取餘等其他運算,除了會發生語法錯誤,也沒有實際的含義。

C中對指標的理解

1.定義乙個指標,有int float double等多種型別指標可定義 int p中如果p不加星號,p裡存放的是位址值,如果加了星號,表示指向之歌位址內所存放的數值。2.int float 這樣表示的是定義乙個空的指標,當使用這種方式時,一般表示要分配一段位址空間,常和malloc new搭配使用...

對C語言指標的理解

c語言中有很多變數,比如說我們常見的int,float變數,而指標變數也是一種變數,不過不一樣的是,指標變數裡面存放的是位址。假設下面的是計算機的記憶體,每乙個小格格代表乙個位元組 1byte 一位元組等於8個位元位 1byte 8bit,能存放8位二進位制數 在c語言中,int佔4個位元組,cha...

對C語言指標的理解

之前,剛剛學習c語言的時候,學習其它資料型別的時候,感覺很好理解,但是學到指標的時候,筆者就蒙蔽了,因為看到課本上的文字,雲裡霧裡的,什麼指標,什麼指標變數,對於筆者來說都是傻傻分不清,感覺指標和指標變數好像一樣,或者試圖去背下來,但是老是搞混。那時候不知道,我的心思是在忙於社團工作,還是在哪個漂亮...