C语言 - 函数指针 | 指针函数

函数指针

1 - 函数指针是指向函数的指针变量,本质是一个指针。声明格式如 int (*maxValue) (int x) 

2 - 函数指针只能指向具有特定特征的函数,要求所有被同一指针所指向的函数必须具有相同的参数和返回值类型

      比如 void (*func) ( ) 首先执行的是 (*func),func 是一个指针;紧接着执行 ( ),表明 func 指向的是一个函数;void 则标明这个函数不返回任何值

3 - 代码示例

① 使用函数指针

复制代码
 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 //
 5 int sumValue(int x,int y){
 6     int sum =0;
 7     sum = x+y;
 8     return sum;
 9 }
10 
11 // 较大值
12 int maxValue(int a,int b){
13     return a > b ? a : b;
14 }
15 
16 // 遍历求和
17 int number (int x){
18 
19     int sum=0;
20     for (int i=0; i<x; i++) {
21         sum += i;
22     }
23     return sum ;
24 }
25 
26 // 平方
27 int squareValue (int y){
28     int square =0;
29     square = y*y;
30     return square;
31 }
32 int main(int argc, const char * argv[]) {
33 
34     //
35     int (*p) (int,int)= sumValue;// 函数指针 p
36     printf("%d \n",sumValue(10, 20));// 方式 1
37     printf("%d \n",p(10,20));   // 方式 2
38     printf("%d \n",(*p)(10,20));// 方式 3
39 
40     printf("%p \n",sumValue);
41     printf("%p \n",p);
42 
43 
44     // 取较大值
45     p = maxValue;// 函数指针重指向,等价于  p = &maxValue;(取址运算符可以忽略)
46     printf("%d \n",maxValue(10, 20));
47     printf("%d \n",p(10,20));
48     printf("%p \n",maxValue);
49     printf("%p \n",p);
50 
51 
52     // 遍历求和
53     int (*q) (int ) = number;
54     printf("%d \n",number(101));
55     printf("%d \n",q(101));
56 
57     // 相加或平方
58     int (*point)(int) = NULL;
59     printf("请输入sum或者squ:\n");
60     char string [20] =" ";
61     scanf("%s",string);
62     if (strcmp(string, "sum")==0) {
63         point = number;
64     }else if(strcmp(string, "squ")==0){
65 
66         point = squareValue;
67     }
68 
69     printf("%s的结果为:%d\n",string,point(10));
70 
71     return 0;
72 }
复制代码

注:C 语言规定函数名既不是左值也不是右值,是 CPP 语言规定函数名属于左值。另外函数指针没有自增 ++ 和 自减 – 操作。函数名除了可以作为 sizeof 和取地址 & 的操作数,函数名在表达式中可以自动转换为函数指针类型的右值。就是说通过一个函数指针调用所指向的函数不需要在函数指针面前添加操作符号 *

指针函数

1 - 简单来说就是一个返回指针的函数。其本质是一个函数,而该函数的返回值是一个指针。声明格式如 int *fun(int x,int y)

2 - 代码示例:输入学生信息(姓名、年龄、分数),以指定分数为标准将学生信息按照年龄进行排序

复制代码
  1 #include <stdio.h>
  2 #include <stdbool.h>
  3 #include <stdlib.h>
  4 
  5 // 学生信息
  6 typedef struct student{
  7 
  8     char  name[20];// 姓名
  9     float score;   // 分数
 10     int   age;     // 年龄
 11 
 12 }Student;
 13 
 14 // 遍历学生信息
 15 void printStudentInfo(Student *stus,int count){
 16     printf("\n----------------------------------\n");
 17     for (int i=0; i<count ; i++) {
 18         printf("姓名:%s, 成绩:%.2f,年龄:%d \n",stus[i].name,(stus+i)->score,stus[i].age);
 19     }
 20     printf("----------------------------------\n");
 21 }
 22 
 23 //---------------------------------------------------------未优化前使用函数指针作参
 24 // 在名字后面拼接标记
 25 void modifyName(char *name){
 26     strcat(name, "---学霸");
 27 }
 28 void Name(char *name){
 29     strcat(name, "---学渣");
 30 }
 31 
 32 // 查找分数:高于指定分数标记为学霸,低于指定分数标记为学渣
 33 // @stus    学生
 34 // @count   学生总数
 35 // @destScore 分数分界线
 36 // @void(*p)(char*)、void(*q)(char*) 函数指针
 37 //      定义格式同 void modifyName(char *name)、 void Name(char *name)
 38 //      注:未使用 typedef 优化,函数指针作参显得晦涩难懂,代码不清晰、不简洁
 39 void searchStudentInfo(Student *stus,int count,float destScore,void(*p)(char*),void(*q)(char*)){
 40 
 41     for (int i = 0;i< count ;i++) {
 42 
 43         if ((stus+i)->score > destScore) {
 44             
 45             // 函数指针
 46             p((stus+i)->name);// 学霸
 47         }else{
 48             q((stus+i)->name);// 学渣
 49         }
 50     }
 51 }
 52 
 53 
 54 //-------------------------------------------------使用 typedef 优化
 55 // 升序
 56 bool isAscending(int age1,int age2){
 57     return age1 > age2 ? 1 : 0;
 58 }
 59 
 60 // 降序
 61 bool isDecending(int age1,int age2){
 62     return age1 < age2 ? 1 : 0;
 63 }
 64 
 65 bool(*p) (int,int);
 66 // 使用 typedef 优化函数指针
 67 typedef bool(*Compare) (int,int);
 68 // 排序
 69 // @point  typedef 优化后的函数指针
 70 void sortStudentInfo(Student *stus,int count,Compare point){
 71 
 72     // 冒泡排序
 73     for(int i=0; i<count-1; i++) {
 74         for(int j=0; j<count-1-i; j++) {
 75 
 76             if(point ((stus+j)->age,(stus+j+1)->age)){
 77                 Student temp = *(stus+j);
 78                 *(stus+j) = stus[j+1];
 79                 *(stus+j+1) = temp;
 80             }
 81         }
 82     }
 83 }
 84 
 85 
 86 
 87 // ----- 注意这里是指针函数 ------
 88 Student *genterStudentsInfo(int count){
 89     
 90     // 开辟内存用来存储学生信息
 91     Student *stus = malloc(sizeof(Student)*count );
 92     
 93     for (int i = 0; i < count; i++) {
 94         printf("请输入第%d个学生的信息:\n",i+1);
 95         printf("姓名 成绩 年纪:\n");
 96         scanf("%s %f %d",(stus+i)->name,&(stus+i)->score,&(stus+i)->age);
 97     }
 98     return stus;
 99 };
100 
101 
102 
103 int main(int argc, const char * argv[]) {
104 
105     // 开辟 3 个内存空间
106     Student *students =  genterStudentsInfo(3);
107     
108     // 区分学霸和学渣
109     searchStudentInfo(students, 3, 90, modifyName,Name);
110     
111     // 按照年龄排序
112     sortStudentInfo(students, 3, isAscending);// 升序
113     
114     // 打印学生信息
115     printStudentInfo(students, 3);
116 
117     return 0;
118 }
复制代码

日志信息

 

posted on   低头捡石頭  阅读(313)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2018-04-08 UI基础 - UIPickerView
2018-04-08 UI基础 - UISearchBar
2018-04-08 UI基础 - UITextView
2018-04-08 UI基础 - UIWebView | 已弃用 |
2018-04-08 UI基础 - UISegmentedControl
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示