C語(yǔ)言指針詳細(xì)解析
概述
????指針也就是內(nèi)存地址,指針變量是用來(lái)存放內(nèi)存地址的變量,不同類型的指針變量所占用的存儲(chǔ)單元長(zhǎng)度是相同的,而存放數(shù)據(jù)的變量因數(shù)據(jù)的類型不同,所占用的存儲(chǔ)空間長(zhǎng)度也不同。有了指針以后,不僅可以對(duì)數(shù)據(jù)本身,也可以對(duì)存儲(chǔ)數(shù)據(jù)的變量地址進(jìn)行操作。
????指針是一個(gè)占據(jù)存儲(chǔ)空間的實(shí)體在這一段空間起始位置的相對(duì)距離值。在C/C++語(yǔ)言中,指針一般被認(rèn)為是指針變量,指針變量的內(nèi)容存儲(chǔ)的是其指向的對(duì)象的首地址,指向的對(duì)象可以是變量(指針變量也是變量),數(shù)組,函數(shù)等占據(jù)存儲(chǔ)空間的實(shí)體。
指針
????數(shù)據(jù)存儲(chǔ)在內(nèi)存中,內(nèi)存又被分為一塊一塊的,每一塊都有一個(gè)特有的編號(hào)。而這個(gè)編號(hào)可以暫時(shí)理解為指針,就像房屋的編號(hào)。特點(diǎn)的房間可以找到特點(diǎn)的人,例如張三要去找李四,那么就要去到李四家,才能找到李四。
????總結(jié)一下,其實(shí)指針就是變量,用來(lái)存放地址的變量(存放在指針中的值都當(dāng)成地址處理)。

指針運(yùn)算符
&:取地址運(yùn)算符&是用來(lái)取操作對(duì)象的地址,它返回運(yùn)算對(duì)象的內(nèi)存地址。
*:指針運(yùn)算符&作用是通過(guò)操作對(duì)象的地址,獲取存儲(chǔ)的內(nèi)容也稱為“間接引用操作符”。
示例

指針類型
????變量有不同的類型,整型,浮點(diǎn)型等等。指針同樣是有類型的,定義如下。
????指針類型的定義方式就是type + * 。其實(shí)上面代碼中char* 就是為了存放char類型變量的地址,short*就是為了存放short類型變量的地址。其他同樣。
示例

????從上述例程得知,指針加1或減1運(yùn)算,表示指針向前或向后移動(dòng)一個(gè)單元(不同類型的指針,單元長(zhǎng)度不同),指針的類型決定了指針向前或者向后走一步有多大距離。
????指針變量的自增自減運(yùn)算。指針加 1 或減 1 運(yùn)算,表示指針向前或向后移動(dòng)一個(gè)單元(不同類型的指針,單元長(zhǎng)度不同)。這個(gè)在數(shù)組中非常常用。
????指針變量加上或減去一個(gè)整形數(shù)。和第一條類似,具體加幾就是向前移動(dòng)幾個(gè)單元,減幾就是向后移動(dòng)幾個(gè)單元。
指針變量的初始化
????指針初始化是將變量的地址分配給指針變量的過(guò)程,指針變量與其它變量一樣,在定義時(shí)可以賦值,即初始化。也可以賦值“NULL”或“0”,如果賦值“0”,此時(shí)的“0”含義并不是數(shù)字“0”,而是 NULL 的字符碼值。
????指針變量在定義時(shí)如果未初始化,那么該指針就是野指針,野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒(méi)有明確限制的),其值是隨機(jī)的,指針變量的值是別的變量的地址,意味著指針指向了一個(gè)地址是不確定的變量,此時(shí)去解引用就是去訪問(wèn)了一個(gè)不確定的地址,所以結(jié)果是不可知的。
關(guān)系運(yùn)算
????假設(shè)有指針pa,pb,那么其關(guān)系運(yùn)算主要有下列三種。
pa > pb,表示 pa 指向的存儲(chǔ)地址大于 pb 指向的地址。
pa == pb,表示 pa 和 pb 指向同一個(gè)存儲(chǔ)單元。
pa == 0 ,表示 pa 是否為空指針。
示例

數(shù)組
一維數(shù)組
????不管什么變量都有地址,數(shù)組包含若干個(gè)元素,但是每個(gè)數(shù)組元素也在內(nèi)存中占用存儲(chǔ)單元,所以也有相對(duì)應(yīng)的地址。指針變量既然可以指向變量,同樣也可以指向數(shù)組元素。
????在數(shù)組中,數(shù)組名即為該數(shù)組的首地址,對(duì)該指針進(jìn)行加減,就可以實(shí)現(xiàn)指針訪問(wèn)數(shù)組元素。

示例

????由上述的結(jié)果可以得知:
p 指向數(shù)組Num的第一個(gè)元素,則此操作將 Num第一個(gè)元素11,即Num[0] = 11。
數(shù)組名是地址,可以稱作數(shù)組地址,也可以看成第一個(gè)元素的地址,通過(guò)+整數(shù)可以移動(dòng)到想要操作的元素。
p+1操作為指針加整數(shù)操作,即向前移動(dòng)一個(gè)單元。此時(shí) p + 1 指向Num[0]的下一個(gè)元素,即Num[1]。通過(guò)p + 整數(shù)的操作可以移動(dòng)到想要操作的元素。
在 p+整數(shù)的操作要考慮邊界的問(wèn)題,如一個(gè)數(shù)組長(zhǎng)度為5,p+6的意義對(duì)于數(shù)組操作來(lái)說(shuō)沒(méi)有意義。
二維數(shù)組
????二維數(shù)組其實(shí)可以看成是一個(gè)矩陣,zai C語(yǔ)言中,定義一個(gè)數(shù)組num[3][4],可以看成是一個(gè)3行4列的矩陣,在內(nèi)存中每一個(gè)位置存儲(chǔ)一個(gè)數(shù)據(jù),用a[i][j]表示。
????二維數(shù)組實(shí)際上就是元素為一維數(shù)組的數(shù)組,二維數(shù)組名可以看做指向其第一個(gè)元素(一維數(shù)組)的指針。

示例

字符串指針
????對(duì)于字符,在計(jì)算機(jī)內(nèi)部都是用數(shù)字(字符編碼)來(lái)表示的,而字符串是“字符連續(xù)排列”的一種表現(xiàn)。字符串就是每個(gè)元素內(nèi)都存儲(chǔ)著字符的一維數(shù)組,通常稱之為字符數(shù)組。
????在 C語(yǔ)言中,因?yàn)樽址麛?shù)組的元素內(nèi)存儲(chǔ)的都是 char 型的字符,所以字符數(shù)組的數(shù)據(jù)類型是 char 型,因而字符串實(shí)際上就是一個(gè) char 型的一維數(shù)組。
在 C語(yǔ)言中,可以用兩種方法訪問(wèn)一個(gè)字符串:
用字符數(shù)組存放一個(gè)字符串,然后輸出該字符串
用字符指針指向一個(gè)字符串
????字符串中包含的字符的個(gè)數(shù)就是這個(gè)字符串的長(zhǎng)度。C語(yǔ)言中用字符數(shù)組存儲(chǔ)字符串時(shí)在字符串的末端都要加一個(gè)字符“\0”來(lái)表示這個(gè)字符串的結(jié)束,這個(gè)“\0”稱為字符串結(jié)束符。因而在定義字符數(shù)組時(shí),數(shù)組大小應(yīng)為要存儲(chǔ)的字符串長(zhǎng)度的最大值加 1。
示例

????字符串指針變量本身是一個(gè)變量,用于存放字符串的首地址。而字符串本身是存放在以該首地址為首的一塊連續(xù)的內(nèi)存空間中并以 \0 作為串的結(jié)束。字符數(shù)組歸根結(jié)底還是一個(gè)數(shù)組,字符串名也可以認(rèn)為是一個(gè)指針。
字符串儲(chǔ)存方式:
字符數(shù)組由一個(gè)或若干元素組成,每個(gè)元素存放一個(gè)字符;
而字符指針變量只存放字符串的首地址,不是整個(gè)字符串;
????字符串存儲(chǔ)位置:
數(shù)組是在內(nèi)存中開辟了一段空間用于存放字符串;
字符指針是在文字常量區(qū)開辟了一段空間存放字符串,將字符串的首地址賦值給指針變量。
示例

????由上圖可以得知,數(shù)組是在內(nèi)存中開辟了一段空間用于存放字符串,故數(shù)組越大,所占的數(shù)據(jù)大小越大;字符指針是在文字常量區(qū)開辟了一段空間存放字符串,故字符指針是只想這個(gè)文字常量區(qū)的地址。
指針函數(shù)
????指針函數(shù)就是一個(gè)返回值為指針的函數(shù),指針函數(shù)是指帶指針的函數(shù),函數(shù)返回類型是某一類型的指針,即本質(zhì)是一個(gè)函數(shù)。
????函數(shù)定義:類型標(biāo)識(shí)符 * 函數(shù)名(參數(shù)表)
????普通的函數(shù)定義如下所示。
????指針函數(shù)定義如下所示。
????普通的函數(shù)與指針函數(shù)只是多了一個(gè)*號(hào)的區(qū)別。上述定義的指針函數(shù)其返回值是一個(gè) int 類型的指針,是一個(gè)地址,而上述普通函數(shù)返回的是一個(gè)int值。所以指針函數(shù)一定有函數(shù)返回值,同時(shí)函數(shù)返回值必須賦給同類型的指針變量。
示例

????上面示例定義了fun和fun1函數(shù),同時(shí)在函數(shù)內(nèi)用指針p指向了sum變量,但是函數(shù)執(zhí)行完之后會(huì)釋放函數(shù),雖然最后return返回了該地址的指針,但是由于空間以及釋放,故不一定會(huì)得到正確的值,需要用static去修飾變量,使得其變?yōu)殪o態(tài)變量。靜態(tài)變量一旦生成,只有在程序結(jié)束才會(huì)釋放,所以指針能一直訪問(wèn)該變量。
????同樣的使用全局變量也能解決這個(gè)問(wèn)題。
函數(shù)指針
????函數(shù)指針是指帶指針的函數(shù),函數(shù)指針的本質(zhì)是一個(gè)指針,該指針的地址指向了一個(gè)函數(shù),所以它是指向函數(shù)的指針。函數(shù)指針就是指向代碼段中函數(shù)入口地址的指針。
????函數(shù)定義:類型標(biāo)識(shí)符 (*函數(shù)名) (參數(shù))
????普通的函數(shù)定義如下所示。
????函數(shù)指針聲明格式。
????其中,int 為返回值,(*fun)作為一個(gè)整體,代表的是指向該函數(shù)的指針,(int x,int y)為形參列表。其中fun被稱為函數(shù)指針變量 。函數(shù)指針本質(zhì)是一個(gè)指針,其指向一個(gè)函數(shù)。
????函數(shù)指針與數(shù)組類似,在數(shù)組中,數(shù)組名代表著該數(shù)組的首地址,函數(shù)也是一樣,函數(shù)名即是該數(shù)組的入口地址,因此,函數(shù)名就是該函數(shù)的函數(shù)指針。
????函數(shù)指針是需要把一個(gè)函數(shù)的地址賦值給它,因此,可以采用如下的兩種方式。
示例

????上面示例定義了sum求和函數(shù)和Difference求差函數(shù),可見函數(shù)指針fun指向函數(shù)的時(shí)候,可以添加取址符&,也可以不添加,所指向的為函數(shù)的入口。
指針函數(shù)和函數(shù)指針
定義
????指針函數(shù)本質(zhì)是一個(gè)函數(shù),其返回值為指針。
函數(shù)指針本質(zhì)是一個(gè)指針,其指向一個(gè)函數(shù)。
寫法
????指針函數(shù):int* fun(int x,int y);
????函數(shù)指針:int (* fun)(int x,int y);
用途
????當(dāng)項(xiàng)目比較大,代碼變得復(fù)雜了以后,有許多的函數(shù)的返回值,包括函數(shù)入?yún)⒍际窍嗤?,這時(shí)候如果要調(diào)用不同的排序方法,就可以使用指針函數(shù)來(lái)實(shí)現(xiàn),我們只需要修改函數(shù)指針初始化的地方,而不需要去修改每個(gè)調(diào)用的地方。