入門(7)指針)
一、指針基礎(chǔ)概念1. 地址與指針內(nèi)存以字節(jié)為最小單位每個字節(jié)擁有唯一編號這個編號就是內(nèi)存地址。指針 內(nèi)存地址地址就是指針指針指向一塊內(nèi)存空間。指針變量專門用來存儲內(nèi)存地址的變量自身會占用內(nèi)存空間。2. 指針變量定義語法基類型 *變量名;基類型決定指針指向空間存儲的數(shù)據(jù)類型決定解引用時讀取多少字節(jié)*類型標(biāo)記代表該變量是指針int *pint; // 指向int類型的指針 char *pch; // 指向char類型的指針 float *pf; // 指向float類型的指針 int *pi, *pj; // 同時定義兩個int指針指針占用空間64 位系統(tǒng)所有指針統(tǒng)一占8 字節(jié)32 位系統(tǒng)所有指針統(tǒng)一占4 字節(jié)printf(指針大小%lu\n, sizeof(int*));3. 指針初始化與賦值int num 100; // 合法初始化 int *p NULL; // 空指針推薦默認初始化方式 int *p2 num; // 存儲變量num的地址 p num; // 運行時賦值野指針高危問題定義未初始化、指向已釋放內(nèi)存、非法地址的指針。 危害解引用野指針會造成程序崩潰、內(nèi)存錯亂。 規(guī)避方案指針定義時默認賦值NULL僅賦值合法變量 / 數(shù)組的地址4. 兩個核心運算符1 取地址運算符作用獲取變量首字節(jié)內(nèi)存地址 規(guī)則只能作用于變量不能對常量、表達式取地址int a 10; printf(a的地址%p\n, a);2* 解引用指針運算符作用通過指針存儲的地址訪問對應(yīng)內(nèi)存的數(shù)據(jù)p保存的地址值*p地址對應(yīng)內(nèi)存里的數(shù)據(jù)類型等于指針基類型int num 20; int *p num; *p 666; // 修改num的值 printf(num %d\n, num); // 輸出666內(nèi)存讀取字節(jié)規(guī)則char*解引用讀取 1 字節(jié)int*解引用讀取 4 字節(jié)double*解引用讀取 8 字節(jié)5. 指針?biāo)阈g(shù)運算僅、--、整數(shù)、-整數(shù)、指針-指針有意義* / %無任何使用價值指針 n向后偏移n * sizeof(基類型)字節(jié)指針 - n向前偏移n * sizeof(基類型)字節(jié)指針1 - 指針2計算兩個指針之間相隔的元素個數(shù)int arr[5] {1,2,3,4,5}; int *p arr; p; // 向后偏移4字節(jié)指向arr[1]二、指針作為函數(shù)參數(shù)地址傳遞核心作用在被調(diào)函數(shù)中修改主調(diào)函數(shù)的變量值傳遞做不到函數(shù)需要返回多個結(jié)果時通過指針參數(shù)帶出多組數(shù)據(jù)傳遞數(shù)組 / 大塊數(shù)據(jù)避免完整拷貝節(jié)省內(nèi)存開銷示例交換兩個數(shù)字值傳遞失敗地址傳遞成功#include stdio.h // 值傳遞無法交換主函數(shù)變量 void swap_err(int a, int b) { int tmp a; a b; b tmp; } // 地址傳遞通過指針修改外部變量 void swap(int *pa, int *pb) { int tmp *pa; *pa *pb; *pb tmp; } int main(void) { int x 10, y 20; swap_err(x, y); printf(錯誤交換x%d y%d\n, x, y); swap(x, y); printf(正確交換x%d y%d\n, x, y); return 0; }三、指針與一維整形數(shù)組1. 數(shù)組名本質(zhì)數(shù)組名arr等價于arr[0]是首元素地址常量右值不能賦值修改 尋址等價公式plaintextarr[i] ? *(arr i) arr[i] ? arr i2. 一維數(shù)組兩種傳參寫法完全等價// 寫法1數(shù)組形式 void print_arr(int a[], int len); // 寫法2指針形式底層完全一致 void print_arr(int *pa, int len);完整遍歷示例#include stdio.h void print_arr(int *pa, int len) { for(int i 0; i len; i) { printf(%d , *(pa i)); } } int main(void) { int arr[5] {11,22,33,44,55}; int len sizeof(arr)/sizeof(arr[0]); print_arr(arr, len); return 0; }四、拓展區(qū)分指針數(shù)組 vs 數(shù)組指針1. 指針數(shù)組char *str[]數(shù)組里每一個元素都是字符指針存儲多個字符串的地址內(nèi)存不連續(xù)。char *name[] {張三, 李四, 王五};2. 數(shù)組指針char str[][16]二維字符數(shù)組整塊連續(xù)內(nèi)存每行存放一個完整字符串函數(shù)傳參必須指定列數(shù)。char name[3][16] {張三, 李四, 王五};高頻面試坑二者不可互相作為函數(shù)參數(shù)傳遞內(nèi)存布局完全不同。五、萬能指針 void*void*可以接收任意類型變量、數(shù)組的地址使用前必須強制轉(zhuǎn)換為對應(yīng)類型指針才能解引用int num 100; void *p num; // 解引用需要強制轉(zhuǎn)換 printf(%d\n, *(int*)p);未完結(jié)待更新