一、用指针变量作函数参数的实例

思考题:
例题:从键盘输入某班学生某门课成绩(每班人数最多不超过40人,具体人数由键盘输入),是分析下列程序是否能实现计算并输出最高分以及相应学号。

#include <stdio.h>
#define N 40
void FindMax(int score[],long num[],int n,int pmaxscore,long pmaxnum);
int main(void)
{int score[N],maxscore;int n,i;long num[N],maxnum;printf("How many students?");scanf("%d",&n);printf("Input student`s ID and score:\n");for(i=0;i<n;i++){scanf("%ld%d",&num[i],&score[i]);}FindMax(score,num,n,maxscore,maxnum);printf("maxscore = %d,maxnum = %ld\n",maxscore,maxnum);return 0;} void FindMax(int score[],long num[],int n,int pmaxscore,long pmaxnum){int i;pmaxscore = score[0];pmaxnum = num[0];for(i=1;i<n;i++){if(score[i]>pmaxscore){pmaxscore = score[i];pmaxnum = num[i];}}}


错误的原因在于用普通变量作函数参数进行按值调用不能再被调函数中改变相应的参数值。虽然可以用return 语句返回最高值,但return 只能返回一个值,要的到最高分即学号这样的两个值,必须使用指针变量作函数参数,即模拟按引用调用,因此需要将程序修改如下:

#include <stdio.h>
#define N 40
void FindMax(int score[],long num[],int n,int *pmaxscore,long *pmaxnum);
int main(void)
{int score[N],maxscore;int n,i;long num[N],maxnum;printf("How many students?");printf("\n");scanf("%d",&n);printf("Input student`s ID and score:\n");for(i=0;i<n;i++){scanf("%ld%d",&num[i],&score[i]);}FindMax(score,num,n,&maxscore,&maxnum);printf("maxscore = %d,maxnum = %ld\n",maxscore,maxnum);return 0;} void FindMax(int score[],long num[],int n,int *pmaxscore,long *pmaxnum){int i;*pmaxscore = score[0];*pmaxnum = num[0];printf("\n");for(i=1;i<n;i++){if(score[i]>*pmaxscore){*pmaxscore = score[i];*pmaxnum = num[i];}}}

指针梳理:创建变量pmaxscore pmaxnum为整形,“FindMax(score,num,n,&maxscore,&maxnum);”
这句中&调用地址,传递给findmax,再通过值得对比,获得最大值,
“printf(“maxscore = %d,maxnum = %ld\n”,maxscore,maxnum);”
这句打印得就是获得得最大值。

由于指针形参所指向的变量的值在函数调用结束后才能被确定,因此这两个指针形参称为函数的出口参数,函数FindMax()的前三个形参再函数调用前必须确定其值,因此称为函数的入口参数。

这个题目得另一个解法:(我只做简要得原理论述,程序相对简单,容易理解)

#include <stdio.h>
#define n 4
int score[n];void Sum(int score[],int *sum)
{int i;for(i=1;i<n;i++){*sum=*sum+score[i];}
}int main()
{int *sum=&score[0];int i;printf("shuru:");for(i=0;i<n;i++){scanf("%d",&score[i]);} Sum(score,sum);printf("%d",*sum);
}

该程序通过直接获取数组首地址,传入函数Sum中,进行处理,最后返回需要得答案。

指针得使用非常重要,需要读者进行理解,练习。

二、函数指针及其应用
函数指针(Function Pointers)就是指向函数得指针(Pointer to a Function)
指向函数得指针变量存储得是一个函数再内存中得入口地址。
冯·诺依曼体系结构强调程序与数据共同存储再内存中,函数是子程序,当然也存储在内存中,指向存储这个函数得第一条指令得地址,称为函数得入口地址。
在前面我们了解到一个数组名其实就是存储数组第一个元素得内存地址,同理,一个函数名就是这个函数得源代码在内存中得起始地址,编译器将不带()得函数名解释为该函数得入口地址,函数指针在某些场合是非常有用的。
例题:
对输入学生得数据进行排序(升序、降序)

#include <stdio.h>#define N 40
int readscore(int score[]);
void printscore(int score[],int n);
void ascendingsort(int a[],int n);
void descendingsort(int a[],int n);
void swap(int *x,int *y);int main(void)
{int score[N],n;int order;n=readscore(score);printf("Total students are %d\n",n);printf("Enter 1 to sort in ascending order,\n");printf("Enter 2 to sort in descending order:");scanf("%d",&order);printf("Data items in original order \n");printscore(score,n);if(order==1){ascendingsort(score,n);printf("Data items in ascending order\n");}else{descendingsort(score,n);printf("Data items in descending order\n");}printscore(score,n);return 0;
}int readscore(int score[])
{int i=-1;do{i++;printf("Input score:");scanf("%d",&score[i]);}while(score[i]>=0);return i;
}void printscore(int score[],int n)
{int i;for(i=0;i<n;i++){printf("%4d",score[i]);}printf("\n");
}void ascendingsort(int a[],int n)
{int i,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++){if(a[j]<a[k]) k=j;}if(k!=i) swap(&a[k],&a[i]);}
}void descendingsort(int a[],int n)
{int i,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++){if(a[j]>a[k]) k=j;}if(k!=j) swap(&a[k],&a[i]);}
}void swap(int *x,int *y)
{int temp;temp=*x;*x=*y;*y=temp;
}



修改程序,将升降排序合二为一:

#include <stdio.h>#define N 40
int readscore(int score[]);
void printscore(int score[],int n);
void selectionsort(int a[],int n,int (*compare)(int a,int b));
int ascendingsort(int a,int b);
int descendingsort(int a,int b);
void swap(int *x,int *y);int main(void)
{int score[N],n;int order;n=readscore(score);printf("Total students are %d\n",n);printf("Enter 1 to sort in ascending order,\n");printf("Enter 2 to sort in descending order:");scanf("%d",&order);printf("Data items in original order \n");printscore(score,n);if(order==1){selectionsort(score,n,ascendingsort);//函数指针指向ascending() printf("Data items in ascending order\n");}else{selectionsort(score,n,descendingsort);//函数指针指向descending()printf("Data items in descending order\n");}printscore(score,n);return 0;
}int readscore(int score[])
{int i=-1;do{i++;printf("Input score:");scanf("%d",&score[i]);}while(score[i]>=0);return i;
}void printscore(int score[],int n)
{int i;for(i=0;i<n;i++){printf("%4d",score[i]);}printf("\n");
}
//函数功能:调用函数指针compare指向得函数实现对数组a的交换法排序
void selectionsort(int a[],int n,int (*compare)(int a,int b))
{int i,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++){if((*compare)(a[j],a[k]))k=j;}if(k!=i)  swap(&a[k],&a[i]);}}
int ascendingsort(int a,int b)
{return a<b;
}
int descendingsort(int a,int b)
{return a>b;
}void swap(int *x,int *y)
{int temp;temp=*x;*x=*y;*y=temp;
}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FJntlZWx-1686370230305)(null)]
过于int (*compare)(int a,int b)
圆括号的优先级是最高的,因此这句话可以解释为:
compare-----> * -------> ( ) ------->int
他告诉编译器函数selectionsort()的这个形参compare是一个指针类型,该指针变量可以指向一个两个整形形参、返回值为整形的函数。即compare是一个函数指针。这里,*compare两侧的圆括号必不可少,他将 * 和compare先结合,表示compare是一个指针变量。然后,(*compare)与其后的()结合,表示该指针变量可以指向一个函数。

如果少去了compare两边的括号,就会变成
compare-----》()-------》 * ---------》 int
因此,它声明的不是一个函数指针,而是一个两个整型形参并返回整形指针的函数。

指针--用指针变量作函数参数的实例(按值调用与模拟按引用调用)、函数指针及其应用相关推荐

  1. C++模板学习02(类模板)(类模板语法、类模板与函数模板的区别、类模板中的成员函数创建时机、类模板对象做函数参数、类模板与继承、类模板成员函数类外实现、类模板分文件编写、类模板与友元)

    C++引用详情(引用的基本语法,注意事项,做函数的参数以及引用的本质,常量引用) 函数高级C++(函数的默认参数,函数的占位参数,函数重载的基本语法以及注意事项) C++类和对象-封装(属性和行为作为 ...

  2. python函数定义与参数_Python函数的定义方式与函数参数问题实例分析

    本文实例讲述了Python函数的定义方式与函数参数问题.分享给大家供大家参考,具体如下: 涉及内容: 函数的定义方式 函数的文字描述 空操作语句 位置参数 默认参数 关键参数 可变长度参数 函数的定义 ...

  3. mysql调用java函数_mysql概要(十五)存储过程(2)(java调用函数和存储过程)

    使用存储过程的目的: 即将数据的函数处理放在数据库,这样主要是为了,多语言跨平台的使用(java,.net,php),不用重复的函数代码,直接调用存储过程. (对于使用存储过程还是代码来处理数据的效率 ...

  4. 编写函数 int fac(int x)计算 x!的值。在主函数中输入 n 和 m 的值,通过调用函数 fac 计算m Cn 的值(要求分别用递归和非递归的方法编写函数 fac)

    编写函数 int fac(int x)计算 x!的值.在主函数中输入 n 和 m 的值,通过调用函数 fac 计算m Cn 的值(要求分别用递归和非递归的方法编写函数 fac) 递归: #includ ...

  5. c语言让参数等于空字符串,C语言模拟实现字符串操作函数

    前言 在编写程序过程中,我们经常使用到一些字符串函数,例如求字符串长度,拷贝字符串--,这些函数都在C标准库中存在,我们可以直接使用.但我们还需要掌握这些函数的实现方法,今天来看看一些常用的字符串操作 ...

  6. 数组作为函数参数时,最好将数组大小也作为一个函数参数

    1.一个好的习惯:当数组作为函数参数时,最好将数组大小也作为函数的一个参数. 2.如果数组大小不确定,再加上可能代码写的不严谨,可能导致数组溢出(数组越界),然而编译器也不报错的情况,比如下面这个例子 ...

  7. oracle revers函数,Oracle SQL 语句中对Like的优化(引用reverse函数)

    重点关注reverse 用法:reverse(字段)like reverse(属性值); 实际例子体现出得查询效率: select Max(Ana_Rqb_Date) from Ana_Rqb whe ...

  8. 实验六(函数) 2.编写函数 int fac(int x)计算 x!的值。在主函数中输入 n 和 m 的值,通过调用函数 fac 计算Cnm 的值(要求分别用递归和非递归的方法编写函数 fac)。

    (Cnm是m在上n在下) 非递归法: #include<stdio.h>long fac(long);int main(){long m,n,a=1,b;scanf("%ld%l ...

  9. [JavaSE](static关键字、继承、super关键字、this关键字、多态、(成员变量、静态成员方法、实例成员方法)在多态中的调用情况)

    ✨✨个人主页:沫洺的主页

最新文章

  1. 小程序云开发更新数组的指定对象的值
  2. XAML Region标签功能
  3. 分页浏览的导航栏Bootstrap和js两种方法
  4. 解决Red hat 5.4的中文问题
  5. 安卓自定义时间选择器_微信小程序拾色器(颜色选择器)组件
  6. Spring Security加密策略
  7. SpringCloud微服务注册调用入门-路由网关
  8. FreeSwitch命令:切换视频会议画面布局
  9. 复选框java_java之swing实现复选框的方法
  10. 解决管家婆7在SQL2008上安装不了问题
  11. P12证书转BKS证书
  12. Unity3D实现3D立体游戏原理及过程
  13. 华为运营商级路由器配置示例 | 公网IPv6 over SRv6 TE Policy
  14. mac下 iterm+Zsh+Oh My Zsh+tmux 配置方案
  15. CYCADA: cycle-consistent adversaial domain adaption阅读笔记
  16. 导游APP开发模板现源码
  17. 南京大学计算机专硕和学硕几年制,专硕人数连续4年超过学硕,报考专硕更吃香吗?...
  18. linux 普通用户修改密码
  19. 6万字新型智慧城市一网统管顶层设计方案
  20. 考研英语阅读理解做题技巧(2):主旨题

热门文章

  1. iMeta | 中大李文均组描绘不同极端环境原核微生物培养策略
  2. 2.Java语言概述
  3. 寓言故事《听风就是雨的狼》
  4. 继奇瑞小蚂蚁之后奇瑞新能源的又一力作,奇瑞无界Pro正式上市
  5. goccess 导出html设置参数,GoAccess中文界面显示配置
  6. Allegro制作4层PCBA板的练习-非接触式传感器
  7. [leetcode] 517. Super Washing Machines
  8. Redis(一)入门:NoSQL OR SQL,看完这篇你就懂了
  9. Re-ID的评价标准
  10. 【腾讯云原生降本增效大讲堂】Caelus全场景在离线混部