c理解提高(4)指標知識體系
指標知識體系搭建
前言
先從整體上把握指標的知識體系。然後突破1級指標、二級指標、多級指標。
指標強化
鐵律1:指標是一種資料型別
1)指標也是一種變數,佔有記憶體空間,用來儲存記憶體地址
測試指標變數佔有記憶體空間大小
2)*p操作記憶體
在指標宣告時,*號表示所宣告的變數為指標
在指標使用時,*號表示 操作 指標所指向的記憶體空間中的值
*p相當於通過地址(p變數的值)找到一塊記憶體;然後操作記憶體
*p放在等號的左邊賦值(給記憶體賦值)
*p放在等號的右邊取值(從記憶體獲取值)
3)指標變數和它指向的記憶體塊是兩個不同的概念
//含義1 給p賦值p=0x1111; 只會改變指標變數值,不會改變所指的內容;p = p +1; //p++
//含義2 給*p賦值*p='a'; 不會改變指標變數的值,只會改變所指的記憶體塊的值
//含義3 =左邊*p 表示 給記憶體賦值, =右邊*p 表示取值 含義不同切結!
//含義4 =左邊char *p
//
4)指標是一種資料型別,是指它指向的記憶體空間的資料型別
含義1:指標步長(p++),根據所致記憶體空間的資料型別來確定
p++ = (unsigned char )p+sizeof(a);
結論:指標的步長,根據所指記憶體空間型別來定。
注意:
建立指標指向誰,就把把誰的地址賦值給指標。圖和程式碼和二為一。
不斷的給指標變數賦值,就是不斷的改變指標變數(和所指向記憶體空間沒有任何關係)。
鐵律2:間接賦值(*p)是指標存在的最大意義
1)兩碼事:指標變數和它指向的記憶體塊變數
2)條件反射:指標指向某個變數,就是把某個變數地址賦給指標
3)*p間接賦值成立條件:3個條件
a)2個變數(通常一個實參,一個形參)
b) 建立關係,實參取地址賦給形參指標
c) *p形參去間接修改實參的值
Int iNum = 0; //實參
int *p = NULL;
p = &iNum;
iNum = 1;
*p =2 ; //通過*形參 == 間接地改變實參的值
*p成立的三個條件:
4)引申: 函式呼叫時,用n指標(形參)改變n-1指標(實參)的值。
//改變0級指標(int iNum = 1)的值有2種方式
//改變1級指標(eg char *p = 0x1111 )的值,有2種方式
//改變2級指標的(eg char **pp1 = 0x1111 )的值,有2種方式
//函式呼叫時,形參傳給實參,用實參取地址,傳給形參,在被呼叫函式裡面用*p,來改變實參,把運算結果傳出來。
//指標作為函式引數的精髓。
鐵律3:理解指標必須和記憶體四區概念相結合
- 主調函式 被調函式
- 主調函式可把堆區、棧區、全域性資料記憶體地址傳給被呼叫函式
- 被呼叫函式只能返回堆區、全域性資料
- 記憶體分配方式
- 指標做函式引數,是有輸入和輸出特性的。
鐵律4:應用指標必須和函式呼叫相結合(指標做函式引數)
編號 |
指標函式引數 記憶體分配方式(級別+堆疊) |
主調函式 實參 |
被調函式 形參 |
備註
|
||||
01 |
1級指標 (做輸入) |
堆 |
分配 |
使用 |
一般應用禁用 |
|||
棧 |
分配 |
使用 |
常用 |
|||||
Int showbuf(char *p); int showArray(int *array, int iNum) |
||||||||
02 |
1級指標 (做輸出) |
棧 |
使用 |
結果傳出 |
常用 |
|||
int geLen(char *pFileName, int *pfileLen); |
||||||||
03 |
2級指標 (做輸入) |
堆 |
分配 |
使用 |
一般應用禁用 |
|||
棧 |
分配 |
使用 |
常用 |
|||||
int main(int arc ,char *arg[]); 指標陣列 int shouMatrix(int [3][4], int iLine);二維字串陣列 |
||||||||
04 |
2級指標 (做輸出) |
堆 |
使用 |
分配 |
常用,但不建議用,轉化成02 |
|||
int getData(char **data, int *dataLen); Int getData_Free(void *data); Int getData_Free(void **data); //避免野指標 |
||||||||
05 |
3級指標 (做輸出) |
堆 |
使用 |
分配 |
不常用 |
|||
int getFileAllLine(char ***content, int *pLine); int getFileAllLine_Free(char ***content, int *pLine); |
指標做函式引數,問題的實質不是指標,而是看記憶體塊,記憶體塊是1維、2維。
- 如果基礎類int變數,不需要用指標;
- 若記憶體塊是1維、2維。
鐵律5:一級指標典型用法(指標做函式引數)
一級指標做輸入
int showbuf(char *p)
int showArray(int *array, int iNum)
一級指標做輸出
int geLen(char *pFileName, int *pfileLen);
理解
主調函式還是被呼叫函式分配記憶體
被呼叫函式是在heap/stack上分配記憶體
鐵律6:二級指標典型用法(指標做函式引數)
二級指標做輸入
int main(int arc ,char *arg[]); 字串陣列
int shouMatrix(int [3][4], int iLine);
二級指標做輸出
int Demo64_GetTeacher(Teacher **ppTeacher);
int Demo65_GetTeacher_Free(Teacher **ppTeacher);
int getData(char **data, int *dataLen);
Int getData_Free(void *data);
Int getData_Free2(void **data); //避免野指標
理解
主調函式還是被呼叫函式分配記憶體
被呼叫函式是在heap/stack上分配記憶體
鐵律7: 三級指標輸出典型用法
三級指標做輸出
int getFileAllLine(char ***content, int *pLine);
int getFileAllLine_Free(char ***content, int *pLine);
理解
主調函式還是被呼叫函式分配記憶體
被呼叫函式是在heap/stack上分配記憶體
鐵律8:雜項,指標用法幾點擴充
1)野指標 2種free形式
int getData(char **data, int *dataLen);
int getData_Free(void *data);
int getData_Free2(void **data);
2)2次呼叫
主調函式第一次呼叫被呼叫函式求長度;根據長度,分配記憶體,呼叫被呼叫函式。
3)返回值char */int/char **
4)C程式書寫結構
商業軟體,每一個出錯的地方都要有日誌,日誌級別
鐵律9:一般應用禁用malloc/new
附錄
1)指標也是一種資料型別,指標的資料型別是指它所指向記憶體空間的資料型別
2)間接賦值*p是指標存在的最大意義
3)理解指標必須和記憶體四區概念相結合
4)應用指標必須和函式呼叫相結合(指標做函式引數)
指標是子彈,函式是槍管;子彈只有沿著槍管發射才能顯示它的威力;指標的學習重點不言而喻了吧。介面的封裝和設計、模組的劃分、解決實際應用問題;它是你的工具。
5)指標指向誰就把誰的地址賦給指標
6)指標指向誰就把誰的地址賦給指標,用它對付連結串列輕鬆加愉快
7)連結串列入門的關鍵是分清楚連結串列操作和輔助指標變數之間的邏輯關係
8)C/C++語言有它自己的學習特點;若java語言的學習特點是學習、應用、上專案;那麼C/C++語言的學習特點是:學習、理解、應用、上專案。多了一個步驟吧。
9)學好指標才學會了C語言的半壁江山,另外半壁江山在哪裡呢?你猜,精彩剖析在課堂。
10) 理解指標關鍵在記憶體,沒有記憶體哪來的記憶體首地址,沒有記憶體首地址,哪來的指標啊。