:回调函数与sizeof/strlen深度对比)
文章目录前言一、回调函数是什么二、sizeof和strlen的对比1. sizeof2. strlen3. sizeof和strlen的对比总结前言在上一篇中我们学习了函数指针数组及转移表实现了计算器的简化。本篇将进一步探讨函数指针的重要应用——回调函数通过改造计算器代码演示如何将函数地址作为参数传递消除冗余逻辑。同时我们还将对比sizeof与strlen的区别前者是运算符计算内存大小后者是库函数求字符串长度两者在用法和原理上有着本质不同。掌握这些内容您将写出更简洁、更灵活的代码。一、回调函数是什么回调函数就是一个通过函数指针调用的函数如果你把一个函数的指针(地址)作为参数传给另一个函数, 当这个指针被用来调用其所指向的函数时被调用的函数就是回调函数.(被调用的函数是回调函数).回调函数不是由该函数的实现方直接调用而是在特定的事件或条件发生时由另外的一方调用的用于对该事件或条件进行响应。我们来看下面这段代码//使用回调函数改造前#includestdio.hintadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intdiv(inta,intb){returna/b;}intmain(){intx,y;intinput1;intret0;do{printf(************************\n);printf( 1:add 2:sub \n);printf( 3:mul 4:div \n);printf(************************\n);printf(请选择);scanf(%d,input);switch(input){case1:printf(输入操作数);scanf(%d %d,x,y);scanf(%d %d,x,y);retadd(x,y);printf(ret %d\n,ret);break;case2:printf(输入操作数);scanf(%d %d,x,y);retsub(x,y);printf(ret %d\n,ret);break;case3:printf(输入操作数);scanf(%d %d,x,y);retmul(x,y);printf(ret %d\n,ret);break;case4:printf(输入操作数);scanf(%d %d,x,y);retdiv(x,y);printf(ret %d\n,ret);break;case0:printf(退出程序\n);break;default:printf(选择错误\n);break;}}while(input);return0;}我们发现这段代码逻辑相似,有很多重复的地方case1:printf(输入操作数);scanf(%d %d,x,y);scanf(%d %d,x,y);retadd(x,y);printf(ret %d\n,ret);break;case2:printf(输入操作数);scanf(%d %d,x,y);retsub(x,y);printf(ret %d\n,ret);break;case3:printf(输入操作数);scanf(%d %d,x,y);retmul(x,y);printf(ret %d\n,ret);break;case4:printf(输入操作数);scanf(%d %d,x,y);retdiv(x,y);printf(ret %d\n,ret);break;case0:printf(退出程序\n);break;default:printf(选择错误\n);break;我们可不可以想办法给它简化一下呢?这就要用到我们的回调函数了,修改后的代码如下//使用回调函数改造后#includestdio.hintadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}intdiv(inta,intb){returna/b;}voidcalc(int(*pf)(int,int)){intret0;intx,y;printf(输入操作数);scanf(%d %d,x,y);retpf(x,y);printf(ret %d\n,ret);}intmain(){intinput1;do{printf(************************\n);printf( 1:add 2:sub \n);printf( 3:mul 4:div \n);printf(************************\n);printf(请选择);scanf(%d,input);switch(input){case1:calc(add);break;case2:calc(sub);break;case3:calc(mul);break;case4:calc(div);break;case0:printf(退出程序\n);break;default:printf(选择错误\n);break;}}while(input);return0;}我们发现只有调用函数的逻辑是有差异的我们可以把调用的函数的地址以参数的形式传递过去使用函数指针接收函数指针指向什么函数就调用什么函数这里其实使用的就是回调函数的功能。voidcalc(int(*pf)(int,int)){intret0;intx,y;printf(输入操作数);scanf(%d %d,x,y);retpf(x,y);printf(ret %d\n,ret);}二、sizeof和strlen的对比1. sizeof在学习操作符的时候我们学习了sizeof,sizeof计算变量所占内存空间大小的单位是字节如果操作数是类型的话计算的是使用类型创建的变量所占内存空间的大小。sizeof只关注占用内存空间的大小不在乎内存中存放什么数据。#includestdio.hintmain(){inta10;printf(%d\n,sizeof(a));printf(%d\n,sizeofa);printf(%d\n,sizeof(int));return0;}2. strlenstrlen是C语言库函数功能是求字符串长度。函数原型如下:size_tstrlen(constchar*str);统计的是从strlen函数的参数str中这个地址开始向后\0之前字符串中字符的个数。strlen函数会⼀直向后找\0字符直到找到为止所以可能存在越界查找。#includestdio.h#includestring.hintmain(){chararr1[3]{a,b,c};chararr2[]abc;printf(%d\n,strlen(arr1));printf(%d\n,strlen(arr2));printf(%d\n,sizeof(arr1));printf(%d\n,sizeof(arr2));return0;}运行结果:3. sizeof和strlen的对比总结以上就是本篇博客的核心内容。本文介绍了回调函数的概念并通过计算器示例展示了如何使用函数指针作为参数将调用逻辑集中到calc函数中消除了重复代码。同时对比了sizeof与strlensizeof是操作符计算类型或变量所占内存字节数不关注实际数据strlen是库函数统计字符串中\0前的字符个数可能越界查找。理解这两者的区别能避免日常编程中的常见错误。