組配套指針與函數(shù)指針 —— 學習筆記)
附圖完整梳理整套C語言指針知識體系指針底層邏輯、各類指針分類已有完整梳理本文不再贅述。本文圍繞數(shù)組配套指針、函數(shù)指針含函數(shù)指針數(shù)組兩大核心難點展開解析前者依托數(shù)組與指針的內(nèi)在關聯(lián)逐層拆解后者結合指針實操場景逐一闡述。文章目錄數(shù)組配套指針變量 結合數(shù)組與指針內(nèi)在關聯(lián)剖析數(shù)組與指針底層脈絡梳理數(shù)組名底層釋義指針訪問數(shù)組實現(xiàn)指針數(shù)組與數(shù)組指針變量概念辨析指針數(shù)組數(shù)組指針變量函數(shù)指針與函數(shù)數(shù)組指針依托指針實操應用場景闡述函數(shù)指針底層釋義實際應用——回調函數(shù)函數(shù)指針數(shù)組底層釋義實際應用——轉移表小結數(shù)組配套指針變量 結合數(shù)組與指針內(nèi)在關聯(lián)剖析數(shù)組與指針底層脈絡梳理數(shù)組名底層釋義intarr[]{1,2,3,4,5];printf(arr %p, arr); // printf(arr[0]%p,arr[0])數(shù)組名是首元素的地址多數(shù)場景中數(shù)組名 數(shù)組首元素地址arr與arr[0]內(nèi)存一致。但有兩處特例數(shù)組名不再指代首元素sizrof(數(shù)組名:指代完整數(shù)組計算數(shù)組整體占用字節(jié)數(shù)組名:獲取數(shù)組整體地址與首元素地址無關。指針訪問數(shù)組實現(xiàn)由上文可知數(shù)組名等同數(shù)組首元素地址。將該地址賦值給指針變量后依靠指針偏移即可遍歷數(shù)組全部元素。#includestdio.hintmain(){intarr[]{1,2,3,4,5];int*parr;for(inti0;i5;i){printf(%d,*(pi);}return0;}指針數(shù)組與數(shù)組指針變量概念辨析指針數(shù)組指針數(shù)組屬于特殊數(shù)組數(shù)組中每一個元素都是指針同類衍生數(shù)組還有許多例如字符指針數(shù)組浮點型指針數(shù)組。數(shù)組指針變量定義專門用來存儲整個數(shù)組地址的指針intarr[10]{0};int(*p)[10]arr;語法解析[ ]優(yōu)先級高于**p必須加括號不加括號就變成指針數(shù)組后方[10]限制只能指向長度為 10 的 int 數(shù)組僅能賦值arr不能直接寫arr二者類型不匹配核心用途用途 1二維數(shù)組函數(shù)傳參高頻考題#includestdio.h// int (*p)[5] 數(shù)組指針接收3行5列二維數(shù)組每行是長度5的int數(shù)組voidtest(int(*p)[5],intr,intc){inti0;intj0;for(i0;ir;i){for(j0;jc;j){// pi指向第i行的起始地址// *(pi)解引用得到第i行首元素地址// *(pi)j偏移到第i行第j列元素地址// *()取出地址里的數(shù)值printf(%d ,*(*(pi)j));}printf(\n);}}intmain(){intarr[3][5]{{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};test(arr,3,5);return0;}用途 2p1 跳過一整個數(shù)組步長為數(shù)組總字節(jié)int (*p)[5]數(shù)組指針指向長度為 5 的整型數(shù)組p 1不會只偏移 1 個 int而是一次性偏移整個數(shù)組占用的字節(jié)5*420 字節(jié)對比普通 int* 指針步長特性是數(shù)組指針核心考點函數(shù)指針與函數(shù)數(shù)組指針依托指針實操應用場景闡述函數(shù)指針底層釋義普通指針用來存放普通變量、數(shù)組的內(nèi)存地址。函數(shù)指針變量。專門用來存放函數(shù)的入口地址。函數(shù)加載進內(nèi)存會擁有一塊存儲空間擁有起始地址函數(shù)名本身就代表該函數(shù)的入口地址。#includestdio.hvoidtest(inta){printf(%d\n,a);}intmain(void){//定義函數(shù)指針變量(*p)括號不可丟void(*p)(int);ptest;// p test 賦值存入test函數(shù)入口地址p初始為無效隨機值必須賦值才能調用(*p)(200);// (p)(200) 解引用獲取函數(shù)本體完成調用return0;}void (*p)(int); 中(*p)的括號絕對不能丟失。若寫成void *p(int);語義變?yōu)楹瘮?shù)聲明該函數(shù)返回 void*指針不再是函數(shù)指針。C 語言語法特性函數(shù)指針調用時*解引用符號可以省略p()與(*p)()完全等價。實際應用——回調函數(shù)題目要求編寫一款簡易計算器程序借助函數(shù)指針作為入?yún)崿F(xiàn)加、減、乘、除四則運算?;卣{優(yōu)勢代碼解耦通用計算函數(shù)無需綁定具體運算可靈活傳入不同功能函數(shù)#includestdio.hintAdd(intx,inty){returnxy;}intSub(intx,inty){returnx-y;}intMul(intx,inty){returnx*y;}intDiv(intx,inty){returnx/y;}// 回調承載函數(shù)接收函數(shù)指針形參intcalc(intx,inty,int(*fp)(int,int)){returnfp(x,y);// fp接收外部傳入的函數(shù)地址完成回調調用}intmain(){intinput0;intx0;inty0;intr0;do{printf(請選擇);scanf(%d,input);if(input1input4){printf(請輸入2個操作數(shù));scanf(%d%d,x,y);if(input1)rcalc(x,y,Add);elseif(input2)rcalc(x,y,Sub);elseif(input3)rcalc(x,y,Mul);elseif(input4)rcalc(x,y,Div);printf(結果是%d\n,r);}elseif(input0){printf(退出計算器\n);}else{printf(輸入錯誤請輸入0~4的值\n);}}while(input);return0;}拓展typedef 簡化例題內(nèi)的函數(shù)指針類型原始復雜聲明int (*fp)(int,int)代表接收兩個 int、返回 int 類型的函數(shù)指針typedef int (*Func)(int,int);給該函數(shù)指針類型設置別名 Func簡化之后函數(shù)寫法如下typedefint(*Func)(int,int);intcalc(intx,inty,Func fp){returnfp(x,y);}函數(shù)指針數(shù)組底層釋義普通數(shù)組存放的是普通數(shù)據(jù)int、char 等。函數(shù)指針數(shù)組數(shù)組里面每一個元素都是函數(shù)指針變量用來存放一批函數(shù)的入口地址。voidfun1(){printf(函數(shù)1\n);}voidfun2(){printf(函數(shù)2\n);}intmain(void){//定義函數(shù)指針數(shù)組void(*pfArr[])(void){fun1,fun2};pfArr[0]();//取下標0的函數(shù)指針調用fun1pfArr[1]();//取下標1的函數(shù)指針調用fun2return0;void (*pfArr[])(void):pfArr[]代表這是一個數(shù)組(*pfArr[])數(shù)組中存儲的是指針void ()指針指向無參、無返回值的函數(shù)實際應用——轉移表題目承接上一道計算器例題使用函數(shù)指針數(shù)組搭建轉移表完成四則運算。如將加、減、乘、除四個函數(shù)的入口地址全部存入函數(shù)指針數(shù)組依靠輸入的選項下標直接調用對應運算函數(shù)。轉移表優(yōu)勢利用數(shù)組下標直接索引對應函數(shù)替代冗長的 if?else /switch 分支#includestdio.hintAdd(intx,inty){returnxy;}intSub(intx,inty){returnx-y;}intMul(intx,inty){returnx*y;}intDiv(intx,inty){returnx/y;}// fp 就是函數(shù)指針變量intcalc(intx,inty,int(*fp)(int,int)){returnfp(x,y);}intmain(){intinput0;intx0;inty0;intr0;do{printf(請選擇);scanf(%d,input);if(input1input4){printf(請輸入2個操作數(shù));scanf(%d%d,x,y);if(input1)rcalc(x,y,Add);elseif(input2)rcalc(x,y,Sub);elseif(input3)rcalc(x,y,Mul);elseif(input4)rcalc(x,y,Div);printf(結果是%d\n,r);}elseif(input0){printf(退出計算器\n);}else{printf(輸入錯誤請輸入0~4的值\n);}}while(input);return0;}擴展typedef 簡化寫法// 給函數(shù)指針類型起別名typedefint(*Func)(int,int);// 1、函數(shù)指針變量回調使用intcalc(intx,inty,Func fp){returnfp(x,y);}// 2、函數(shù)指針數(shù)組轉移表專用Func pfArr[]{NULL,Add,Sub,Mul,Div};小結函數(shù)指針變量單個指針存放一個函數(shù)地址多用于回調函數(shù)指針數(shù)組數(shù)組容器存放一組函數(shù)地址用作轉移表依靠下標選擇調用函數(shù)