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

news2024/12/29 10:37:13

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

思考题:
例题:从键盘输入某班学生某门课成绩(每班人数最多不超过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
因此,它声明的不是一个函数指针,而是一个两个整型形参并返回整形指针的函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/630487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

群晖 NAS 外网访问设置 - 腾讯 DNSPod

目录 ​编辑 一、使用DNSPod&#xff0c;实现DDNS&#xff08;动态域名&#xff09; 二、公共概念厘清 三、腾讯DNSPod上详细设置步骤 1. 打开DNSPod.cn网站并登录 2. 登录成功后&#xff0c;选择【我的域名】-> 【添加域名】 3. 添加群晖NAS需要二级域名&#xff08…

Visual Studio封装静态链接库至新静态库,供程序调用

熟悉Windows开发的人都肯定了解静态链接库和动态链接库。 最近遇到一个问题&#xff1a; A静态库是使用VS编译&#xff0c;因为C版本的问题&#xff0c;并不能直接在Qt中被调用&#xff0c;因为会报头文件某处错误。 因为A库很大&#xff0c;同时又不想修改太多A库源文件&#…

开源社章程(2023版)

第 1 条 开源社是由志愿贡献于开源事业的个人志愿者&#xff0c;依 “贡献、共识、共治” 原则所组成的开源社区。第 2 条 开源社的英文名称为“KAIYUANSHE”&#xff0c;官方网站地址为 https://kaiyuanshe.cn/第 3 条 开源社的愿景为&#xff1a;立足中国、贡献全球&#xff…

English Learning - L3 作业打卡 Lesson5 Day36 2023.6.9 周五

English Learning - L3 作业打卡 Lesson5 Day36 2023.6.9 周五 引言&#x1f349;句1: So next time you are on a train, look around and see what other people are reading, but dont jump to any conclusions.成分划分弱读连读爆破语调 &#x1f349;句2: You will probab…

MIT 6.S081 Lab One

MIT 6.S081 Lab One 引言sleep(难度&#xff1a;Easy)解析Lab代码实现 pingpong&#xff08;难度&#xff1a;Easy&#xff09;Lab代码实习 小结 引言 本文为 MIT 6.S081 2020 操作系统 实验一解析。 MIT 6.S081课程前置基础参考: 基于RISC-V搭建操作系统系列 sleep(难度&…

English Learning - L3 作业打卡 Lesson5 Day34 2023.6.7 周三

English Learning - L3 作业打卡 Lesson5 Day34 2023.6.7 周三 引言&#x1f349;句1: The woman reading the romantic novel could be a lawyer.成分划分弱读连读爆破语调 &#x1f349;句2: She just wants a light read to take her mind off work.成分划分弱读连读爆破语调…

STM32读取MQ2烟雾浓度数据判断烟雾是否超标

【1】MQ2传感器是什么&#xff1f; MQ2传感器是一种可探测多种气体的传感器&#xff0c;常用于监测烟雾、液化气、丙酮、乙醇、甲醛、天然气等有害气体。MQ2传感器基于半导体敏感元件&#xff0c;通过检测气体中有害物质的浓度变化来实现气体检测。 MQ2传感器具有以下特点&a…

Python的self作用,以及__init__,__new__

本章来探讨一下Python类的self作用&#xff0c;以及__init__,__new__。 为什么是探讨&#xff0c;不是学习&#xff0c;因为菜&#x1f40e;&#xff1b; 先看个例子&#xff1a; class Example:def animal(self):self.dog "大黄"def Dog(self):print(self.dog)if _…

【前端 - CSS】第 10 课 - CSS 引入方式

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、CSS 引入方式 2.1、内部样式表 2.2、外部样式表 2.3、行内样式 3、总结 1、缘起 要想在 HTML 代码中写入 CSS 代…

English Learning - L3 作业打卡 Lesson5 Day33 2023.6.6 周二

English Learning - L3 作业打卡 Lesson5 Day33 2023.6.6 周二 引言&#x1f349;句1: And theres a student reading an English textbook.成分划分弱读连读语调 &#x1f349;句2: What do their choices say about them?成分划分连读爆破语调 &#x1f349;句3: Do you jud…

nodejs+vue+Express论坛网站34t91

本论坛网站有管理员&#xff0c;用户&#xff0c;普通管理员。管理员功能有个人中心&#xff0c;用户管理&#xff0c;普通管理员管理&#xff0c;论坛类别管理&#xff0c;交流论坛管理&#xff0c;系统管理等。用户功能有个人中心&#xff0c;交流论坛管理&#xff0c;我的收…

华为OD机试真题 JavaScript 实现【水仙花数】【2022Q4 100分】

一、题目描述 所谓水仙花数&#xff0c;是指一个n位的正整数&#xff0c;其各位数字的n次方和等于该数本身。 例如153是水仙花数&#xff0c;153是一个3位数&#xff0c;并且153 1^3 5^3 3^3。 二、输入描述 第一行输入一个整数n&#xff0c;表示一个n位的正整数。n在3到…

单容水箱建模(自衡单容水箱+无自衡单容水箱)

自衡单容水箱Simulink建模和PLC源代码请参看下面文章链接: 单容双容水箱建模(simulink仿真+PLC代码)_RXXW_Dor的博客-CSDN博客PLC通过伯努利方程近似计算水箱流量详细内容请参看下面的文章博客PLC通过伯努利方程近似计算水箱流量(FC)_怎么用伯努利方程求某水位流量_RXXW_Dor的…

基础汇编语言编程

目录 什么是汇编语言&#xff1f; 工程搭建 新建工程 环境设置 测试是否成功 正式学习汇编语言 数据处理指令 填充&#xff0c;加&#xff0c;减&#xff0c;乘 思考&#xff1a;我们可以看到R0寄存器可以存放8位十六进制数&#xff0c;那么0x12345678能不能用mov存入&am…

java SSM 摄影作品网站myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM 摄影作品网站系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…

会用Python做副业的人,有多豪横!

前两天一个朋友找到我吐槽&#xff0c;说工资一发交完房租水电&#xff0c;啥也不剩&#xff0c;搞不懂朋友圈里那些天天吃喝玩乐的同龄人钱都是哪来的&#xff1f; 确实如此&#xff0c;刚毕业的大学生工资起薪都很低&#xff0c;在高消费、高租金的城市&#xff0c;别说存钱…

浏览器跨域请求

跨域是浏览器的一种同源策略&#xff0c;所以该概念只存在于通过浏览器访问服务里。 如果缺少了同源策略&#xff0c;则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的&#xff0c;浏览器只是针对同源策略的一种实现 请求的url地址,必须与浏览器上的…

Vue3 ElementPlus Dialog封装 (二:使用provide inject)

引言 上一章Vue3 ElementPlus Dialog封装 &#xff08;一&#xff1a;使用props emit&#xff09; propemit实现的方法用于父子组件比较方便, 跨多层次组件比较麻烦 vue3 中 还提供了provide和inject方法供组件间通信(参考官网图片), 本篇使用该方法实现上章效果 实现原理 参考…

K8S之Ingress 对外暴露应用(十四)

• Ingress为弥补NodePort不足而生 • Pod与Ingress的关系 • Ingress Controller • Ingress 规则配置 一&#xff0c;Ingress为弥补NodePort不足而生 NodePort存在的不足&#xff1a; • 一个端口只能一个服务使用&#xff0c;端口需提前规划 • 只支持4层负载均衡二&#x…

九耶丨阁瑞钛伦特-大型计算机硬件组成(二)

TSO&#xff1a; TSO是Time Sharing Option的缩写&#xff0c;用户可以通过TSO命令和系统进行交互式工作。TSO命令直接使用并不方便&#xff0c;所以IBM又在TSO下开发了程序产品ISPF/PDF&#xff08;Interactive System Productivity/Program Development Facility)其中ISPF支…