C指針的一些問題

這段時間一直在看C語言方面的內容,爲的是鞏固一下基礎知識,把握一些細節上的東西。

指針一直是C語言中的難點,也是重點。每年的面試題,在這上面來下功夫爲難我們的也不算少數。所以自己把這部分又複習了一遍,現在把一些重點的東西寫下來。


指針的概念


指針是一個特殊的變量,它裏面存儲的數值被解釋成內存裏的一個地址,要搞清楚一個指針需要搞清指針的四方面的內容:(1)、指針的類型。(2)、指針所指向的類型。(3)、指針的值或者叫指針所指向的內存區。(4)指針本身所佔據的內存區。

現在我們用例子分別說明。

(1) int *ptr;

(2) char *ptr;

(3) int **ptr;

(4) int (*ptr)[3];

(5) int *(*ptr)[4];


1、指針的類型

從語法的角度看,只要我們把指針聲明語句裏的指針名字去掉,剩下的部分就是這個指針的類型。這事指針本身所具有的類型。例如:

(1) int *ptr;//指針的類型是 int*

(2) char *ptr; //指針的類型是 char *

(3) int **ptr; //指針的類型是 int **

(4) int (*ptr)[3]; //指針的類型是 int (*)[3]

(5) int *(*ptr)[4]; //指針的類型是 int *(*)[4]


2、指針所指向的類型

當你通過指針來訪問指針所指向的內存區時,指針所指向的類型決定了編譯器將把那片內存區裏的內容當作什麼來看待。

從語法上來看,我們只須把指針聲明語句中的指針名字和名字左邊的指針聲明符*去掉,剩下的就是指針所指向的類型。例如:

(1) int *ptr;//指針所指向的類型是 int

(2) char *ptr; //指針所指向的類型是 char

(3) int **ptr; //指針所指向的類型是 int *

(4) int (*ptr)[3]; //指針所指向的類型是 int ()[3]

(5) int *(*ptr)[4]; //指針所指向的類型是 int *()[4]

在指針的算術運算中,指針所指向的類型有很大的作用。


3、指針的值——或者叫指針所指向的內存區或地址

指針的值是指針本身存儲的數值,這個值將被編譯器當作是一個地址,而不是一個一般的數值。在32位程序裏,所有類型的指針的值都是一個32位整數,因爲32位程序裏內存地址全都是32位長。指針所指向的內存區就是從指針的值所代表的那個內存地址開始,長度爲sizeof(指針所指向的類型)的一片內存區。以後,我們說一個指針的值是XX,就相當於說該指針指向了以XX爲首地址的一片內存區域;我們說一個指針指向了某塊內存區域,就相當於說該指針的值是這塊內存區域的首地址。

指針所指向的內存區和指針所指向的類型是兩個完全不同的概念。在上面所舉的例子中,指針所指向的類型已經有了,但由於指針還未初始化,所以它所指向的內存區是不存在的,或者說是無意義的。


4、指針本身所佔據的內存區

指針本身佔了多大的內存,只要用函數sizeof(指針的類型)測一下就知道了。在32位平臺裏,指針本身佔據了4個字節的長度。

指針本身佔據的內存這個概念在判斷一個指針表達式是否是左值時很有用。


指針的算術運算


指針可以加上或減去一個整數。指針的這種運算的意義和通常的數值加減運算意義是不一樣的,以單元爲單位。

一個指針ptrold加(減)一個整數後n後,結果是一個新的指針ptrnew,ptrold的類型和ptrnew的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值增加(減少)了n乘sizeof(ptrold所指向的類型)個字節。就是說,ptrnew所指向內存區將比ptrold所指向的內存區高(低)地址方向移動了n乘sizeof(ptrold所指向的類型)個字節。

兩個指針不能進行加法運算,這事非法操作,因爲進行加法後,得到的結果指向一個不知所向的地方,而且毫無意義。兩個指針可以進行減法操作,但必須類型相同,一般用在數組方面。

有效的指針運算包括:(1)、相同類型指針之間的賦值運算。(2)、指針同整數之間的加法或減法運算。(3)、指向相同數組中元素的兩個指針間的減法或比較運算。(4)將指針賦值爲0或指針與0之間的比較運算。


指針和數組


數組名和指針之間有一個不同之處。指針是一個變量,因此,在C語言中,語句pa = a和pa++都是合法的。但數組名不是變量,因此,類似於a = pa和a++形式的語句都是非法的。

聲明瞭一個數組的數組TYPE array[n],則數組名稱array就有兩重含義:第一,它代表整個數組,它的類型是TYPE[n];第二,它是一個常量指針,該指針的類型是TYPE*,該指針指向的類型是TYPE,也就是數組的單元的類型,該指針指向的內存區就是數組第0號單元,該指針自己佔有單獨的內存區,注意它和數組第0號單元佔據的內存區是不同的。該指針的值是不能修改的,即類似array++的表達式是錯誤的。

在不同的表達式中數組名array可以扮演不同的的角色。(1)、在表達式sizeof(array)中,數組名array代表數組本身,故這時sizeof函數測出的是整個數組的大小。(2)、在表達式*array中,array扮演的是指針,因此這個表達式的結果就是數組第0號單元的值。sizeof(*araay)測出的是數組單元的大小。(3)、表達式array+n中,array扮演的是指針,故array+n的結果是一個指針,它的類型是TYPE*,它指向的類型是TYPE,它指向數組第n號單元。sizeof(array+n)測出的是指針類型的大小。在32位程序中結果是4.









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章