1,指針鐵律 1.1,指針是一種資料類型 1, 指針也是一種變量,占有記憶體空間,用來儲存記憶體位址。 指針既然是變量也要占用記憶體大小。一級指針的大小于其類型有關,二級以及二級以上的指針的大小是四個位元組(32位機) 2,*p操作記憶體 在指針聲明時,*号表示所聲明的變量為指針
在指針使用時,*号表示 操作 指針所指向的記憶體空間中的值
*p 相當于通過位址(p 變量的值)找到一塊記憶體;然後操作記憶體 *p 放在等号的左邊指派(給記憶體指派) 如 *p = 10; *p 放在等号的右邊取值(從記憶體擷取值) int a = *p; 3,指針變量和它指向的記憶體塊是兩個不同的概念 //含義 1 給 p 指派 p=0x1111; 隻會改變指針變量值(改變其指向), 不會改變所指的内容; p = p +1;p++加的是其步長而不是真正的1 //含義 2 給*p 指派*p='a'; 不會改變指針變量的值,隻會改變所指的記憶體塊的值
//含義 3 =左邊*p 表示 給記憶體指派, =右邊*p 表示取值 含義不同切結!
//含義 4 =左邊 char *p //含義 5 保證所指的記憶體塊能修改 4,指針是資料類型,是指 它指向記憶體空間的資料類型 含義 1:指針步長(p++) ,根據所緻記憶體空間的資料類型來确定 p++= ->(unsigned char )p+sizeof(a); 結論:指針的步長,根據所指記憶體空間類型來定。 注意: 建立指針指向誰,就把把誰的位址指派給指針. 不斷的給指針變量指派,就是不斷的改變指針變量(和所指向記憶體空間沒有任何關
1.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,來改變實參,把運算結果傳出來。 //指針作為函數參數的精髓。 1.3:了解指針必須和記憶體四區概念相結合 1)主調函數 被調函數 a) 主調函數可把堆區、棧區、全局資料記憶體位址傳給被調用函數 b) 被調用函數隻能傳回堆區、全局資料,不能傳回棧上資料 2)記憶體配置設定方式 a) 指針做函數參數,是有輸入和輸出特性的。 1.4:應用指針必須和函數調用相結合(指針做函數參數)
指針做函數參數,問題的實質不是指針,而是看記憶體塊,記憶體塊是 1 維、2 維。 1)如果基礎類 int 變量,不需要用指針; 2)若記憶體塊是 1 維、2 維,需要指針。 1.5:一級指針典型用法(指針做函數參數) 一級指針做輸入int showbuf(char *p)int showArray(int *array, int iNum)
一級指針做輸出int geLen(char *pFileName, int *pfileLen); 了解 主調函數還是被調用函數配置設定記憶體 被調用函數是在 heap/stack 上配置設定記憶體 1..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 上配置設定記憶體 1.7: 三級指針輸出典型用法 三級指針做輸出 int getFileAllLine(char ***content, int *pLine); int getFileAllLine_Free(char ***content, int *pLine); 了解 主調函數還是被調用函數配置設定記憶體 被調用函數是在 heap/stack 上配置設定記憶體 1.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 程式書寫結構 商業軟體,每一個出錯的地方都要有日志,日志級别 1. 9:一般應用禁用 malloc/new 因為使用malloc/new就會伴随着記憶體洩漏
二級指針與多級指針 使用指針申請二維空間 #include <stdio.h> #if 0
//利用傳回值進行申請不連續的二維空間
void ** Shenqin(int base,int row,int line)
{
void **p = (void **)malloc(sizeof(void*)*row);
for(int i = 0;i<row;i++)
{
p[i] = (void *)malloc(base*line);
}
return p;
}
#endif
#if 0
//利用三級指針 參數進行申請不連續的二維空間
void Shenqin(void ***p,int base,int row,int line)
{
*p = (void**)malloc(sizeof(void*)*row);//*p可以把***p降級為**p
for(int i =0;i<row;i++)
{
(*p)[i] = (void*)malloc(base*line);
}
}
#endif
#if 1
//申請連續的二維空間
void ** Shenq(int base,int row,int line)
{
void **p = (void**)malloc(sizeof(int*)*row);
void *p1 = (void *)malloc(base*row*line);
int (*PA)[line] =p1;
for(int i =0;i<row;i++)
{
p[i]=PA++;
}
return p;
}
//連續的二維空間的釋放
void Free(void **p)
{
free(p[0]);
free(p);
}
#endif
#if 1
//不連續的二維空間的釋放
void FreeKongjian(void **p,int row)
{
for(int i = 0;i<row;i++)
{
free(p[i]);
}
free (p);
}
#endif
int main(void)
{
// int **p = Shenqin(sizeof(int),3,4);
//int **p=NULL;
// Shenqin(&p,sizeof(int),3,4);
int **p =Shenq(sizeof(int),3,4);
for(int i = 0;i<3;i++)
{
for(int j = 0;j<4;j++)
p[i][j]=i+j;
}
for(int i = 0;i<3;i++)
{
for(int j = 0;j<4;j++)
printf("%d ",p[i][j]);
putchar(10);
}
Free(p);
// FreeKongjian(p,3);
return 0;
}
2, 指針和數組的巨大差別
3,字元與一級指針的記憶體模型
4, const基礎 int main() {
const int a; //
int const b;
const char *c;
char * const d; char buf[100]
const char * const e ; return 0; } int func1(const )
初級了解:const 是定義常量==》const 意味着隻讀
含義:
//第一個第二個意思一樣 代表一個常整形數
//第三個 c 是一個指向常整形數的指針(所指向的記憶體資料不能被修改,但是本身可以修改)
//第四個 d 常指針(指針變量不能被修改,但是它所指向記憶體空間可以被修改)
//第五個 e 一個指向常整形的常指針(指針和它所指向的記憶體空間,均不能被修改)
Const 好處
//合理的利用 const,
//1 指針做函數參數,可以有效的提高代碼可讀性,減少 bug;
//2 清楚的厘清參數的輸入和輸出特性
結論:
//指針變量和它所指向的記憶體空間變量,是兩個不同的概念。 。 。 。 。 。 //看 const 是放在*的左邊還是右邊 看 const 是修飾指針變量,還是修飾所指向的記憶體空變
二位數組圖解