C 语言学习笔记——11(函数指针与指针函数)

张开发
2026/4/10 5:30:04 15 分钟阅读

分享文章

C 语言学习笔记——11(函数指针与指针函数)
下面通过一系列由浅入深的 C 语言例子详细说明指针函数返回指针的函数和函数指针指向函数的指针的区别与用法最终结合结构体展示高级应用。一、基础概念区分术语定义示例声明指针函数一个函数其返回值类型是指针int* func();函数指针一个指针它指向某个函数的入口int (*p)(int);二、指针函数返回指针的函数例1返回静态局部变量的地址浅#includestdio.hint*getPositive(){staticintarr[]{1,2,3};// 静态数组生命周期贯穿程序returnarr;// 返回数组首地址int*}intmain(){int*pgetPositive();for(inti0;i3;i){printf(%d ,p[i]);// 输出 1 2 3}return0;}⚠️ 注意绝不能返回局部普通变量的地址因为函数结束后其内存被回收。使用static或动态分配内存是安全的。例2返回动态分配的内存地址深一层#includestdio.h#includestdlib.h#includestring.hchar*duplicateString(constchar*src){if(!src)returnNULL;char*dst(char*)malloc(strlen(src)1);if(dst)strcpy(dst,src);returndst;// 返回堆内存指针}intmain(){char*msgduplicateString(Hello, pointer function!);if(msg){printf(%s\n,msg);free(msg);// 记得释放内存}return0;}三、函数指针指向函数的指针例3简单函数指针调用浅#includestdio.hintadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmain(){int(*p)(int,int);// 声明函数指针可指向返回int、两个int参数的函数padd;printf(add: %d\n,p(5,3));// 输出8psub;printf(sub: %d\n,p(5,3));// 输出2return0;}例4函数指针作为函数参数中#includestdio.h// 定义一个操作类型接收两个int返回inttypedefint(*Operation)(int,int);intadd(inta,intb){returnab;}intmul(inta,intb){returna*b;}// 高阶函数接收一个操作函数指针intcalculate(intx,inty,Operation op){returnop(x,y);}intmain(){printf(add: %d\n,calculate(10,20,add));printf(mul: %d\n,calculate(10,20,mul));return0;}例5结构体中的函数指针中高#includestdio.h#includestring.h// 定义“动物”结构体包含数据成员和“方法”函数指针typedefstruct{charname[32];intage;void(*speak)(constchar*);// 函数指针指向说话行为}Animal;// 具体的行为实现voiddogSpeak(constchar*name){printf(%s says: Woof! Woof!\n,name);}voidcatSpeak(constchar*name){printf(%s says: Meow~\n,name);}intmain(){Animal dog{Buddy,3,dogSpeak};Animal cat{Kitty,2,catSpeak};dog.speak(dog.name);cat.speak(cat.name);return0;}例6结构体 函数指针 返回函数指针的指针函数深场景一个工厂函数根据传入的类型返回对应的函数指针即选择不同的行为。#includestdio.h#includestdlib.h#includestring.h// 定义“计算器”函数指针类型typedefint(*CalcFunc)(int,int);// 具体算法intadd(inta,intb){returnab;}intsub(inta,intb){returna-b;}intmul(inta,intb){returna*b;}// 定义策略结构体包含名称和对应的函数指针typedefstruct{charop[8];CalcFunc func;}CalcStrategy;// 指针函数根据操作符字符串返回对应的函数指针CalcFuncgetCalculator(constchar*op){// 静态策略表也可以动态创建这里用静态数组staticCalcStrategy table[]{{add,add},{sub,sub},{mul,mul}};intsizesizeof(table)/sizeof(table[0]);for(inti0;isize;i){if(strcmp(op,table[i].op)0){returntable[i].func;// 返回函数指针}}returnNULL;// 未找到}intmain(){CalcFunc fgetCalculator(mul);if(f){printf(Result: %d\n,f(6,7));// 输出42}fgetCalculator(add);if(f){printf(Result: %d\n,f(100,200));// 输出300}return0;}例7复杂结构体 函数指针作为成员 动态分发最深度模拟一个简单的图形面积计算系统使用结构体存储类型和计算面积的函数指针并使用指针函数来创建不同的图形对象。#includestdio.h#includestdlib.h#includemath.h// 前置声明typedefstructShapeShape;// 函数指针类型计算面积的函数参数为Shape*返回doubletypedefdouble(*AreaFunc)(constShape*);// 图形结构体包含类型标识、特定数据用union和面积计算方法指针structShape{inttype;// 0: circle, 1: rectangleunion{struct{doubleradius;}circle;struct{doublewidth,height;}rect;}data;AreaFunc area;// 函数指针};// 具体面积实现doublecircleArea(constShape*s){doublers-data.circle.radius;returnM_PI*r*r;}doublerectangleArea(constShape*s){returns-data.rect.width*s-data.rect.height;}// 指针函数创建圆形对象返回Shape*Shape*createCircle(doubleradius){Shape*s(Shape*)malloc(sizeof(Shape));if(!s)returnNULL;s-type0;s-data.circle.radiusradius;s-areacircleArea;returns;}// 指针函数创建矩形对象Shape*createRectangle(doublew,doubleh){Shape*s(Shape*)malloc(sizeof(Shape));if(!s)returnNULL;s-type1;s-data.rect.widthw;s-data.rect.heighth;s-arearectangleArea;returns;}intmain(){Shape*shapes[2];shapes[0]createCircle(5.0);shapes[1]createRectangle(4.0,6.0);for(inti0;i2;i){if(shapes[i]){printf(Area: %.2f\n,shapes[i]-area(shapes[i]));free(shapes[i]);}}return0;}该例中函数指针area作为结构体成员实现多态。指针函数createCircle/createRectangle返回动态分配的Shape*指针。四、总结指针函数本质是函数返回一个地址指针。常用于返回字符串、数组、结构体指针或动态内存。函数指针本质是指针保存函数的入口地址。用于回调函数、策略模式、动态绑定等。两者结合结构体可以实现类似 C 中类的简单封装和多态行为是 C 语言高级编程的重要技巧。通过以上例子从最简单的返回静态数组到动态内存分配再到结构体成员函数指针最后模拟图形工厂可以全面理解这两个概念的区别与协作。

更多文章