ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

C语言中的指针函数和函数指针

C语言中的指针函数和函数指针 指针函数和函数指针这对词语总是让人迷惑其实只是语法长得像造成极易混淆。先来说明它们的区别项目指针函数函数指针本质函数指针写法int *func(int a)int (*p)(int a)含义函数执行完返回一个指针保存函数的入口地址可以调用函数括号位置*和返回类型在一起func是函数名(*p)整体内存函数在代码段返回值指针指向数据区p变量本身在栈存函数地址然后逐一展开介绍两者定义和实际使用情况一、指针函数–返回指针的函数1、定义本质是一个函数这个函数的返回值是指针一般定义形式是数据类型* 函数名 (参数列表)注意不能将具有局部作用域的变量的地址作为函数的返回值因为局部变量的内存空间在函数返回后即被释放而该变量也不再有效可以返回全局、static静态变量、malloc堆内存的地址2、主要应用a标准库就是指针函数b返回堆上malloc开辟的内存地址调用方free释放c返回数组/结构体指针返回对象地址示例代码#includestdio.h#includewindows.h#includemath.hint*get_max(int*a,int*b){if(*a*b){returna;}else{returnb;}}intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);inta10,b20;int*pget_max(a,b);printf(%d\n,*p);return0;}运行结果下面以一个练习计算2个超大数的代码来体现指针函数的应用#includestdio.h#includestring.h#includewindows.h#includemath.h#definemax_len20charbuf_a[max_len]{0};charbuf_b[max_len]{0};charresult[max_len1]{0};//实现字符串输入char*get_arr(intlen,char*tmp){memset(tmp,0,max_len);printf(请输入一个长度%d的大数据\n,len);scanf(%s,tmp);returntmp;}//实现数组逆序char*turn_arr(chara[],intlen,charout[]){//清空临时缓存memset(out,0,max_len);for(inti0;ilen;i){out[i]a[len-i-1];}out[len]\0;returnout;}//实现字符相加voidbig_add(char*buf_a,intlen_a,char*buf_b,intlen_b,char*result){//定义局部变量intcarry0;intmax_llen_alen_b?len_b:len_a;//实现循环相加并存储for(inti0;imax_l;i){intnum1ilen_a?(buf_a[i]-0):0;intnum2ilen_b?(buf_b[i]-0):0;intsumnum1num2carry;result[i]sum%100;carrysum/10;}//处理最高位进位情况if(carry1){result[max_l]carry0;//有进位结束符放在max_l1result[max_l1]\0;}//无进位结束符放在max_lresult[max_l]\0;}//主函数intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);//第一步获取两个大数据get_arr(15,buf_a);get_arr(16,buf_b);//第二步大数据进行逆序输出intlen_astrlen(buf_a);intlen_bstrlen(buf_b);charrev_a[max_len]{0};charrev_b[max_len]{0};turn_arr(buf_a,len_a,rev_a);turn_arr(buf_b,len_b,rev_b);//第三步循环获取相加结果big_add(rev_a,len_a,rev_b,len_b,result);printf(逆向相加的结果%s\n,result);//第四步结果再次逆序输出intres_lenstrlen(result);charfinal_res[max_len1]{0};turn_arr(result,res_len,final_res);printf(最终相加结果是%s\n,final_res);return0;}运行结果二、函数指针–指向函数的指针变量在C程序中可以将函数地址保存在函数指针变量中然后用该指针间接调用函数。1、定义–本质是一个指针变量这个指针保存函数的地址指向一个函数一般定义形式是返回类型 *指针名参数列表函数名和“函数名”都可以直接代表函数地址。2、主要应用a把函数作为参数传给另一个函数内部自动调用#includestdio.h#includewindows.h#includemath.hintadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);//定义函数指针p输入是2个int输出是1个intint(*p)(int,int);padd;//函数名代表函数入口地址printf(两个数的和是%d\n,p(5,4));//等价add(5,4),结果为9psub;//函数名和函数名都可以表示函数的地址printf(两个数的差是%d\n,p(5,4));//等价sub(5,4),结果为1return0;}b在嵌入式、单片机大量使用函数指针作为函数表、跳转表#includestdio.h#includewindows.h#includemath.hvoidadd(inta,intb){printf(两个数之和是%d\n,ab);}voidsub(inta,intb){printf(两个数之差是%d\n,a-b);}intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);//函数指针数组void(*func[])(int,int){add,sub};func[0](5,4);func[1](5,4);return0;}两个运行结果都是如下c、多态事项、接口封装硬件驱动不同硬件统一接口替换不同底层函数eglcd显示切换lcd1、lcd2只需要修改函数指针上层代码不用改动d、信号处理、中断回调单片机中断触发后执行注册好的回调函数。当有参数时函数指针写起来很长工程代码常常使用typedef重命名示例如下#includestdio.h#includewindows.h#includemath.hintadd(inta,intb){printf(两个数之和是%d\n,ab);returnab;}intsub(inta,intb){printf(两个数之差是%d\n,a-b);returna-b;}intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);//定义Func_P为函数指针-类型指向输入2个int参数返回1个inttypedefint(*Func_P)(inta,intb);Func_P padd;p(1,2);psub;p(1,2);return0;}运行结果也可以通过封装通用函数来实现#includestdio.h#includewindows.h#includemath.hintadd(inta,intb){printf(两个数之和是%d\n,ab);returnab;}intsub(inta,intb){printf(两个数之差是%d\n,a-b);returna-b;}//封装通用函数voidcall_def(int(*p)(int,int),intx,inty){p(x,y);}intmain(){SetConsoleOutputCP(65001);SetConsoleCP(65001);call_def(add,1,2);call_def(sub,1,2);return0;}运行结果如下说明函数指针尽量按照定义类型进行赋值否则可能出现值丢失。egint( *p)(int ,int),如果int func (int,char),尽量不要p指向func程序可能可以正常运行但是潜在可能问题。
返回列表