當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 學(xué)習(xí)筆記 > 嵌入式學(xué)習(xí)筆記; c指針詳解很詳細(xì),學(xué)霸總結(jié)
1.1 定義
在計(jì)算機(jī)內(nèi)部存儲(chǔ)器(簡(jiǎn)稱內(nèi)存)中,每一個(gè)字節(jié)單元,都有一個(gè)編號(hào),稱為地址。在C語(yǔ)言中,內(nèi)存單元的地址稱為指針,專門(mén)用來(lái)存放地址的變量,稱為指針變量(pointer variable)。在不影響理解的情況下,把地址、指針、指針變量,都叫指針。
1.2 指針類型
1.2.1 構(gòu)成
目標(biāo)類型 *
-------- -
| |
| +----->數(shù)據(jù)為地址
+----------->任何類型
1.2.2 編碼結(jié)構(gòu);無(wú)符號(hào)整數(shù)
1.2.3 長(zhǎng)度:與機(jī)器位數(shù)有關(guān)
1.2.4 字面常量:NULL (void *)0 //表示指針變量中存的內(nèi)容為0
注意: izeof(指針)一定是等于計(jì)算機(jī)的位數(shù),與目標(biāo)類型無(wú)關(guān)。
1.3 定義指針變量
1.31 定義指針變量的方法:
(1) 確定目標(biāo)(變量)類型:char
(2) 確定指針類型:char *
(3) 定義指針變量:char *p;
實(shí)例:
實(shí)例:針對(duì)c[2][3]
1.3.2 認(rèn)識(shí)指針變量
認(rèn)識(shí)指針變量類型 ---> 認(rèn)識(shí)目標(biāo)類型
1.3.3 語(yǔ)法原理(注意觀察)
變量 變量的指針類型 指向變量的指針變量定義
int a; int * int *pl
int a[3]; int (*)[3] int (*pr)[3];
char *a[3] char *(*)[3] char *(*p)[3];
1.4 取地址運(yùn)算
語(yǔ)法:
&a(變量, 數(shù)組, 函數(shù))
1.5 賦值運(yùn)算
1.5.1 語(yǔ)法:p = a;
1.5.2 操作數(shù)類型:a和p類型相同
1.5.3 運(yùn)算法則
(1) a的類型和p不相同時(shí),編譯器嘗試自動(dòng)轉(zhuǎn)換:
a的類型轉(zhuǎn)為p類型, 但p最好是void * 所有的編譯器都行
(2) a--->p
1.5.4 結(jié)果:p的值,結(jié)果的類型是a的類型。
1.5.5 寫(xiě)運(yùn)算的思路
(1) 確定運(yùn)算符
(2) 確定操作數(shù)(類型)
1.5.6 看運(yùn)算的思路:
(1) 確定操作數(shù)類型
(2) 確定運(yùn)算法則
1.6 求目標(biāo)
1.6.1 語(yǔ)法:*p
1.6.2 操作數(shù)類型:p必須為指針類型,但不能是void*。
1.6.3 法則:如果p = &a; 則 *p 就是a
1.6.4 結(jié)果:a
總結(jié):px — 指針變量,它的內(nèi)容是地址量。
*px — 指針?biāo)赶虻膶?duì)象,它的內(nèi)容是數(shù)據(jù)。
&px — 指針變量占用的存儲(chǔ)區(qū)域的地址,是個(gè)常量。
1.7 移動(dòng)指向
1.7.1語(yǔ)法
p + n
p - n
p++, p--, ++p, --p
實(shí)例:
1.7.2操作數(shù)類型
p:p必須為指針,最好為非void*類型,gcc允許對(duì)void*的指針進(jìn)行移動(dòng)指向,但是其他編譯器不一定可以
n:n必須為整數(shù)
1.7.3 運(yùn)算法則
p + n
向地址增加方向移動(dòng)n個(gè)目標(biāo), 即: p中的地址 + sizeof(目標(biāo)類型也就是*p) * n
注意:sizeof(p)的大小一直為4.注意是sizeof(*p)
gcc允許p為void*,p + n表示將p中的地址加n
p - n
向地址減小方向移動(dòng)n個(gè)目標(biāo), 即: p中的地址 - sizeof(目標(biāo)類型) * n
p++
取p的值,作為結(jié)果,然后p = p + 1
++p
p = p + 1,然后取p的值,作為結(jié)果
p—
取p的值,作為結(jié)果,然后p = p - 1
--p
p = p – 1,然后取p的值,作為結(jié)果
注意:函數(shù)類型的指針不能做加減運(yùn)算。
實(shí)例:
1.8 求指針之間的目標(biāo)個(gè)數(shù)
1.8.1 語(yǔ)法
p1 - p2
1.8.2 操作數(shù)類型
p1和p2必須為相同類型的指針
如果p1和p2的類型都為void * 運(yùn)算前都會(huì)被自動(dòng)轉(zhuǎn)換為long類型
1.8.3. 運(yùn)算法則
(1) p1和p2類型為非void * 時(shí)
(p1中的地址 - p2中的地址) / sizeof(目標(biāo)類型)
(2) p1和p2的類型為void *時(shí)(可能會(huì)有編譯器不支持)
p1中的地址 - p2中的地址
1.8.4 結(jié)果
目標(biāo)個(gè)數(shù)
實(shí)例:
1.9 關(guān)系運(yùn)算
>, >=, <, <=, ==, !=
都可以用到指針類型數(shù)據(jù), 但通常只用== 和 !=
1 語(yǔ)法
p1 == p2
2. 操作數(shù)類型
p1和p2類型相同
3. 運(yùn)算法則
比較p1和p2中的地址
4. 結(jié)果
布爾值
注意:指針的[]運(yùn)算
1.語(yǔ)法:p[n]
2.操作數(shù)類型:p 必須為指針或數(shù)組,n 必須為整數(shù)
3.運(yùn)算法則:p[n] <==> *(p + n)
1.10指針常量
1.10.1定義:只讀的指針變量
例子:
int a = 0;
int * const p1 = &a;(1)
const int *p2 = &a; (2)
int const *p3 = &a; (3)
const int * const p4 = &a; (4)
(1)中p1鎖定,不能p++,或者p=p+1等操作
(2)中 int被鎖定,a的值不能被修改,但p可以操作
(3)同(1)
(4)同(1)+(2)
注意:const int i;
int *const p = &i;//出現(xiàn)警告,因?yàn)槭浅A浚玴認(rèn)為,他的目標(biāo)是可讀可寫(xiě),權(quán)限增加
1.11 數(shù)組 vs 指針
1.11.1 概念
指針數(shù)組: int * pa[5]; //實(shí)質(zhì)是數(shù)組,數(shù)組的元素是指針
數(shù)組指針: int (*pa)[5]; //實(shí)質(zhì)是指針,目標(biāo)類型是個(gè)數(shù)組
數(shù)組的指針:數(shù)組的指針是指數(shù)組在內(nèi)存中的起始地址,即第一個(gè)數(shù)組元素的地址。
1.11.2 一維數(shù)組 vs 指針
(1) 數(shù)組名, 在運(yùn)算中(定義和聲明除外都其他情況都是運(yùn)算,但sizeof和&運(yùn)算外), 可以被理解成指向第1個(gè)元素的指針(常量)
(2) a[n] 等價(jià)于 *(a + n)
(3) &a[n] 等價(jià)于 a + n
總結(jié):數(shù)組類型和指針類型都可以做[]運(yùn)算
指針變量和數(shù)組在訪問(wèn)數(shù)組中元素時(shí),一定條件下其具有相同的形式,因?yàn)橹羔樧兞亢蛿?shù)組名都是地址量。但指針變量和數(shù)組的指針(或叫數(shù)組名)在本質(zhì)上不同,指針變量是地址變量,而數(shù)組的指針是地址常量
理解:由a[n]是一維數(shù)組可以得到:
(1) &a[n][0] 等價(jià)于 a[n]
即: a[n], 在運(yùn)算中, 可以被理解成a[n][0]的指針
即: int *pl = a[n]; 語(yǔ)法正確
(2) a[n][m] 等價(jià)于 *(a[n] + m)
1.12字符指針與字符串
初始化字符指針是把內(nèi)存中字符串的首地址賦予指針,并不是把該字符串復(fù)制到指針中。
注意:在C編程中,當(dāng)一個(gè)字符指針指向一個(gè)字符串常量時(shí),不能修改指針指向的對(duì)象的值。
補(bǔ)充:多級(jí)指針:指向指針的指針