第6章指针电子课件 C语言程序设计.pptx

上传人:春哥&#****71; 文档编号:90587496 上传时间:2023-05-16 格式:PPTX 页数:91 大小:15.63MB
返回 下载 相关 举报
第6章指针电子课件 C语言程序设计.pptx_第1页
第1页 / 共91页
第6章指针电子课件 C语言程序设计.pptx_第2页
第2页 / 共91页
点击查看更多>>
资源描述

《第6章指针电子课件 C语言程序设计.pptx》由会员分享,可在线阅读,更多相关《第6章指针电子课件 C语言程序设计.pptx(91页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第6章指针第6章 指针在前面章节的学习中,我们通过普通变量来直接访问程序内存空间,本章将要学习的指针,提供了另外一种间接访问内存的独特方式。指针是C语言中一种比较特殊的数据类型,存储的是变量的地址,变量能做的事情,指针都能做,正确运用指针,可使程序变得简洁而高效。本章涉及的案例与知识要点如图6-1所示。第6章 指针(1)理解地址的概念。(2)熟练掌握指针的定义和指针的基本操作方法。(3)掌握指针变量作函数参数的方法。(4)理解数组与指针的关系并能使用指针处理数组元素。(5)能够使用指针对字符串进行输入、输出。学习目标CONTENTS案例1:上课教室在哪里案例2:数据交换了吗案例3:冒泡排序再认

2、识案例4:禁用strcpy库函数案例5:指针挑大小案例1:上课教室在哪里某大学计算机应用专业2019年共招收4个班(1901班1904班),上课地点分别在1号教学楼的14341437教室。同学们根据教室地址准确地找到了各自的上课地点。若将教学楼看作计算机的内存,将教室看作一个个内存单元,请编程求出这4个上课教室对应的内存地址。案例1:上课教室在哪里案例描述案例1:上课教室在哪里相关知识地址与指针指针变量的定义与使用1)内存地址2)变量、变量名、变量的地址和变量的值3)指针、变量的指针和指针变量4)数据访问的两种方式1)指针变量的定义2)指针变量的使用1.地址与指针1)内存地址在计算机中,数据是

3、按二进制编码形式(0、1组合)存放在存储器中的。8位二进制数组成一个字节,存储器中一个字节称为一个存储单元,不同的数据类型占用的存储单元个数不等。例如,在VisualC+2010编译器下,字符型数据占用1个内存单元,单精度实数占用4个内存单元。为了能正确访问这些内存单元,系统会为每个内存单元进行统一编号,由于编号是唯一的,可以根据编号找到所需的内存单元。通常把内存单元的编号称为内存地址,简称地址。CPU就是通过内存地址来访问内存单元并进行数据存取(读/写)的。2)变量、变量名、变量的地址和变量的值变量即对应的内存单元。在C语言中,变量必须遵循“先定义,后使用”的原则。变量定义后,编译器为变量分

4、配相应的内存单元,用于存放数据,并将变量名和内存地址对应起来。(1)变量名。变量所占内存单元的名字,是一个合法的C语言标识符。案例1:上课教室在哪里案例1:上课教室在哪里(2)变量的地址。变量占用的内存单元的地址。(3)变量的值。在变量所对应的内存单元中存放的数据。3)指针、变量的指针和指针变量(1)指针。由于通过内存地址能够访问到所需内存单元,所以在C语言中,将内存地址称为指针,可理解为指针“指向”一个内存单元。(2)变量的指针。指向一个变量对应的内存单元,即“变量的地址”。(3)指针变量。在C语言中,用于保存内存单元的地址的变量。通常情况下,把指针变量简称指针,把地址常量简称地址。4)数据

5、访问的两种方式(1)直接访问。一般情况下,可直接通过变量名来获取变量的值,而无须知道每个变量在内存中的具体地址,变量名与具体内存地址的联系由C编译器自动完成。在程序中对变量进行的存取操作,实际上也就是对某个地址的内存单元进行的读/写操作。这种直接按变量的地址存取变量的值的方式,就称为直接访问。例如,存储了数据50的整型变量a(假如编译器为其分配了起始地址为2000的连续4个内存单元),则在直接访问时,就是先找到整型变量a的内存单元起始地址2000,再从2000开始往后连续访问四个内存单元,从而存取数据50,如图6-2(a)所示。(2)间接访问。先定义一个指针,然后将变量的地址赋给指针,再通过指

6、针存取它所指向的内存单元中的数据,这种数据访问方式就称为间接访问。如上例中,需先定义一个指向整型变量a的指针p,将a的起始地址赋给指针p(指针变量里存放地址2000),然后通过指针p来存取变量a的值,如图6-2(b)所示。案例1:上课教室在哪里2.指针变量的定义与使用1)指针变量的定义指针变量是用来存放内存地址的,通常用于存放一个变量的地址,故又称指向变量的指针。定义指针变量与定义普通变量类似,在变量名前加“*”即可,定义格式为:类型名*指针变量名1,*指针变量名2,;例如:int*p1,*p2;/*定义两个指针变量p1、p2,所指向的内存单元中存放的是整型数据*/案例1:上课教室在哪里类型名

7、表示指针所指向的内存单元中存放的数据的类型,“*”是指针的标志,表示该变量是一个指针变量。注意2)指针变量的使用定义指针变量后,要对它进行初始化或赋值后才可以使用。未初始化或未赋值的指针所指向的内存单元是随机的、无法确定的,此时使用它可能导致系统崩溃。为安全起见,一般定义指针变量时就将其初始化为NULL或某个变量的地址。NULL是在头文件stdio.h中预定义的常量,其值为0或0,赋给指针变量后,该指针变量为空指针。注意,此时该指针并不是指向地址为0的内存单元,而是指它是一个确定的值“空”,试图用空指针访问一个存储单元,会得到出错信息。(1)初始化指针变量。有两种方法初始化指针变量,一种是获取

8、变量的地址为指针赋值。需要用到取地址运算符“&”来获取变量的内存地址,使用格式为:&变量名案例1:上课教室在哪里例如:inta=50,*p=NULL;/定义一个int型的变量a,定义一个指向int型数据的指针变量p并初始化为NULL*/p=&a;/将变量a的地址赋给指针p,使p指向变量a所对应的内存单元/另一种是将同类型的其他指针的值赋给该指针变量,两个指针将指向同一片内存单元。例如:int*p=NULL;/定义一个指向int型数据的指针变量p并初始化为NULL/p=q;/q是一个已知且有值的同类型指针变量,赋值后两个指针指向同一片内存/(2)用指针获取数据。用指针获取数据指根据指针变量中存放

9、的地址,访问该地址对应的内存单元,存取其中的数据。需要用到取值运算符“*”,即在指针变量名之前添加“*”,使用格式为:指针变量名案例1:上课教室在哪里例如:inta=50,*p=&a;/定义变量a和指向int型数据的指针变量p并初始化为a的地址/printf(“用指针取值:%dn”,*p);/输出指针变量p所指向的内存单元中存放的数据/(3)指针变量的移动(加减法运算)。当指针指向一串连续的存储单元(如数组)时,指针变量可以通过加减法运算来移动指针,即改变指针的指向,如p+将指针移动到下一个数组元素,p-将指针移动到前一个数组元素。两个指针变量相减,得到两个指针相差的数组元素个数。这里的加1或

10、减1不是指地址加1或减1,而是加上或减去1个数组元素对应的数据类型的字节数,如图6-3所示。案例1:上课教室在哪里综上所述,使用指针变量间接访问数据的步骤可简单归纳为三步:定义指针变量、初始化指针变量和用指针获取数据。间接访问比直接访问麻烦,但在某些场合下只能使用指针间接访问,如用户使用malloc函数、calloc函数和realloc函数申请一块内存空间时,因为没有变量名,所以只能通过首地址(指针)对其进行操作。再如,通过被调用函数改变主调用函数变量的值时,也只能通过指针来实现。案例1:上课教室在哪里案例1:上课教室在哪里案例实现算法分析流程图表达代码实现运行结果1.算法分析将教室看作内存单

11、元,将每个班级看作变量,在编程实现时,可将教室地址设置为指针,它们分别指向1901班1904班各自上课的教室。2.流程图表达程序算法流程如图6-4所示。案例1:上课教室在哪里3.代码实现#include/标准输入/输出函数头文件#include/system()函数头文件intmain()/主程序开始intclass_1901=1434;/定义班级变量,并初始化为教室号intclass_1902=1435;intclass_1903=1436;intclass_1904=1437;int*address1,*address2,*address3,*address4;/定义各班级指针变量以存储/

12、内存地址指针初始化(&),获取各班级的内存地址并赋给相应指针变量(&为取地址运算符)address1=&class_1901;address2=&class_1902;address3=&class_1903;address4=&class_1904;案例1:上课教室在哪里/引用指针(*),输出指针变量所指单元的值及对应的内存地址,%x表示按十六进制输出printf(计应1901班上课地点%d教室的内存地址是:%xn,*address1,address1);printf(计应1902班上课地点%d教室的内存地址是:%xn,*address2,address2);printf(计应1903班上课

13、地点%d教室的内存地址是:%xn,*address3,address3);printf(计应1904班上课地点%d教室的内存地址是:%xn,*address4,address4);system(pause);/暂停屏幕,便于观察,按任意键退出return(0);案例1:上课教室在哪里4.运行结果程序运行结果如图6-5所示。案例1:上课教室在哪里案例2:数据交换了吗使用两种方式用函数实现数据交换功能,一种是普通变量为形参,另一种是指针变量为形参,下面看看这两种方式哪一种真正实现了数据交换。案例2:数据交换了吗案例描述案例2:数据交换了吗相关知识指针作为函数参数指针及其数据的交换1.指针作为函数参

14、数在C语言中,函数调用时实参和形参之间数据的传递原则是单向值传递,即只能由实参传递给形参,而不能由形参传递给实参。指针(地址)作为参数传递,也是单向值传递的,即形参指针不能改变实参指针值(地址)。但由于把实参指针值(地址)传递给了形参指针,形参指针与实参指针具有相同的地址,此时当形参指针改变其所指向的内存单元中存放的数据时,显然就是改变了实参指针所指向的内存单元中的数据,因为二者指向同一片内存单元,数据改变是同步的。使用指针作为函数的形参,通过传递地址的方式,可以达到在被调函数中对主调函数中的数据进行操作的目的。而使用普通变量作为函数的形参,不能在被调用函数中对主调函数的数据进行操作,即无法改

15、变实参的值。案例2:数据交换了吗2.指针及其数据的交换使用指针既可得到变量的地址,又可得到变量的值。因此,指针的交换既包含指针指向的交换,又包含指针指向的内存单元中存放的数据的交换。1)指针指向的交换指针指向的交换同数据的交换类似,要借助一个临时性的辅助指针变量来实现,即先定义一个同类型的辅助指针(temp)记录其中一个指针(p1)原来的指向,然后让该指针(p1)指向另外一个指针(p2),最后另外一个指针(p2)再指向原来的指针(p1)。假设p1、p2都是int型指针,交换两个指针指向的代码如下所示,示意如图6-6所示。int*temp;/*定义辅助指针*temp*/temp=p1;/*辅助指

16、针记录p1的指向(赋值)*/p1=p2;/*指针p1记录指针p2的指向(赋值)*/p2=temp;/*指针p2再指向p1原来的指向(赋值)*/printf(用指针取值:%dn,*p);/输出指针变量p所指向的内存单元中存放的数据案例2:数据交换了吗案例2:数据交换了吗2)数据的交换如果要交换指针所指向的内存单元中的数据,可用之前学习的取值运算符“*”取出指针所指向内存单元中的数据。假设p1、p2都是int型指针,则所指向的数据交换的代码如下,示意图如图67所示。inttemp;/*定义辅助变量temp*/temp=*p1;/*辅助变量记录p1指向的内存单元中的数据*/*p1=*p2;/*取出指

17、针p2指向的内存单元中的数据,并放到指针p1指向的内存单元中*/*p2=temp;/*将p1指向的原来的数据再放回到p2指向的内存单元中*/printf(用指针取值:%dn,*p);/输出指针变量p所指向的内存单元中存放的数据案例2:数据交换了吗案例2:数据交换了吗案例实现算法分析流程图表达代码实现运行结果1.算法分析第一步:根据案例描述,设计3个函数,一个是主函数main、一个是普通变量作形参函数swap_var(intnum1,intnum2)、一个是指针变量作形参函数swap_pointer(int*s,int*t)。第二步:两数交换要借助第三个变量(设为temp),然后依次循环赋值;如

18、果采用指针变量,则须用指针*s、*t取数据,然后依次循环赋值。第三步:在主函数中分别调用两个交换函数,看一看到底哪一个真正交换了数据。2.流程图表达程序算法流程如图6-8所示。案例2:数据交换了吗3.代码实现#include/标准输入/输出函数头文件/#include/system函数头文件/voidswap_var(intnum1,intnum2);/函数声明/voidswap_pointer(int*s,int*t);/函数声明/intmain()/主程序/inta,b;/定义整型变量/int*p1=NULL,*p2=NULL;/定义整型指针,并初始化为NULL/printf(输入两个整数

19、(以空格隔开、以回车结束):);scanf(“%d%d”,&a,&b);/输入两个整数/printf(两数交换位置前:a=%db=%dn,a,b);swap_var(a,b);/调用形参是普通变量的函数,验证两数是否交换位置/printf(普通变量作形参,两数交换位置后:a=%db=%dn,a,b);p1=&a;p2=&b;/获取a、b两数指针并赋值给指针变量/案例2:数据交换了吗swap_pointer(p1,p2);/*调用形参是指针变量的函数,验证两数是否交换位置*/printf(指针变量作形参,两数交换位置后:a=%db=%dn,a,b);system(pause);/*暂停屏幕,便于

20、观察结果,按任意键退出*/return0;/以下是函数定义voidswap_var(intnum1,intnum2)/*普通变量作形参,交换两数位置(此方式不能实现交换)*/inttemp;/*借助中间变量循环赋值*/temp=num1;num1=num2;num2=temp;案例2:数据交换了吗voidswap_pointer(int*s,int*t)/*指针作形参,交换两数位置(此方式可以实现交换)*/inttemp;/*借助中间变量循环赋值*/temp=*s;/*“*”表示取地址中存储的数值(取值运算符)*/s=t;t=temp;案例2:数据交换了吗4.运行结果程序运行结果如图6-9所示

21、。案例2:数据交换了吗案例3:冒泡排序再认识运用函数与指针,重新实现冒泡排序。案例3:冒泡排序再认识案例描述相关知识指针和一维数组数组名与指向一维数组的指针充当函数参数指针与二维数组1.指针和一维数组C语言中数组名代表数组的起始地址,即第一个元素的地址,其地址值是固定不变的。由于数组在内存中占用一片连续的存储空间,因此,用指针变量代替数组名,通过指针的移动来操作数组元素,更加方便执行,效率也更高。1)指向一维数组元素的指针指向一维数组元素的指针的定义方法与指向变量的指针的定义方法相同,在使用上略有不同。指向变量的指针仅仅指向一个变量,由于变量的地址不会被改变,故指针的值也不会改变。而指向一维数

22、组元素的指针可以指向数组中的每一个元素,虽然某一时刻只能指向某一个元素,但是可通过指针的自加或自减运算来移动指针,从而代替数组名来访问数组元素。指向一维数组元素的指针定义方法为:inta10,p=NULL;/定义一个整型数组a与指针p/p=a;/让指针p指向数组(将数组名a,也就是数组的起始地址赋给指针p)/案例3:冒泡排序再认识数组元素ai的地址可以用&ai表示,也可以用a+i表示,还可以用p+i表示。指针与一维数组的关系如图6-10所示。由图610可知,p的值、a的值、&a0的值相等,p+1的值、a+1的值、&a1的值相等,p+i的值、a+i的值、&ai的值相等。需要注意的是,加1不是加1

23、个字节,而是加1个数组元素所占内存单元的数目,如对整型数据就是加4个字节。案例3:冒泡排序再认识2)通过指针引用数组元素通过指针引用数组元素可采用“不移动指针”和“移动指针”两种方法。示例如下。inta10,p=NULL,i;/定义一个整型数组a与指针p及循环控制变量I/p=a;/*让指针p指向数组a,或使用p=&a0;*/案例3:冒泡排序再认识(1)p+是正确的,而a+是错误的。因为a是数组名,是个常量,不能改变;而p是指针变量,值可变,这称为指针的移动,指向下一个数组元素。(2)*p+等价于*(p+)。因为自加+与取值*优先级相同,结合方向自右向左,表示先取值再移动指针。(3)*p+表示先

24、取值再移动指针,而(*p)+则表示指针p所指向的数组元素值加1。注意(1)不移动指针。示例如下。for(i=0;i10;i+)/*输入数组元素,不移动指针*/scanf(%d,p+i);for(i=0;i10;i+)/输出数组元素,不移动指针/printf(%d,*(p+i);printf(%dn,*p);/输出指针变量p所指向的内存单元中存放的数据(2)移动指针。示例如下。for(p=a;pa+10;p+)/*输入数组元素,移动指针*/scanf(%d,p);for(p=a;pa+10;p+)/输出数组元素,移动指针(注意p需要重新初始化为数组名)/printf(%d,*p);案例3:冒泡排

25、序再认识(3)使用带下标的指针来访问数组元素,同数组名加下标方式一样。示例如下。for(i=0;i10;i+)scanf(“%d”,p+i);/输入数组元素/for(i=0;i10;i+)printf(%d,pi);/*使用p下标格式输出数组元素*/2.数组名与指向一维数组的指针充当函数参数数组名是地址,可与指向一维数组元素的指针相配合充当函数的参数,具体使用方式有如下几种。(1)实参是数组名,形参是指针。示例如下。voidfun(int*p)/*函数定义,指针p充当形参*/函数体案例3:冒泡排序再认识main()inta=1,2,3,4,5;fun(a);/函数调用,数组名充当实参/(2)实

26、参是指针,形参是指针。示例如下。voidfun(int*p)/函数定义,指针p充当形参/函数体main()inta=1,2,3,4,5,*p=NULL;p=a;fun(p);/*函数调用,指针p充当实参*/案例3:冒泡排序再认识案例3:冒泡排序再认识(3)实参是数组名,形参是数组名。示例如下。voidfun(intb)/函数定义,数组名充当形参/函数体main()inta=1,2,3,4,5;fun(a);/函数调用,数组名充当实参/(4)实参是指针,形参是数组名。示例如下。voidfun(intb)/函数定义,数组名充当形参/函数体main()inta=1,2,3,4,5,*p=NULL;p

27、=a;fun(p);/函数调用,指针p充当实参/3.指针与二维数组二维数组由行和列组成,每一行相当于一个一维数组。在进行二维数组元素访问时,要先定位行,再定位本行当中的某一列。对于列地址操作方式,与指向一维数组元素的指针相同;对于定位行,即要找到本行(一维数组)的首地址。指向一行的指针称行指针,又称指向一维数组的指针,可理解为数组指针(一个没有数组名的数组,可用指针来进行访问)。相对于行指针,指向一行中某一个元素的指针在二维数组中也可称为列指针。行指针前面加“*”,指针类型就成了列指针。案例3:冒泡排序再认识行指针的定义格式为:类型名(*指针变量名)二维数组第二维的长度值;例如:#includ

28、eintmain()inta33=1,2,3,4,5,6,7,8,9;/*定义一个33的二维数组*/int(*p)3;/定义一个行指针p,指向一个包含3个整型元素的一维数组/int*q;/*定义一个列指针q,指向一维数组中的元素*/p=a;/*数组名赋给p,即把二维数组第一行的首地址赋给行指针,这样一来行指针p便指向了二维数组a的第一行p*/案例3:冒泡排序再认识指针变量名两边的“()”不能少。因为“”运算符的优先级比“*”高,如果少了“()”,变量名会先和“”结合,然后与“*”结合,其含义不再是行指针,而变成了指针数组。注意q=*p;/*把*p的内容(地址)赋给列指针q,即把行指针转换成列指

29、针q,这样通过列指针q可以遍历当前行的各列元素*/printf(a=%x*a=%xn,a,*a);/*输出并比较指针与指针指向的内容*/printf(p=%x*p=%xn,p,*p);/*输出并比较指针与指针指向的内容*/printf(q=%x*q=%xn,q,*(q+2);/*输出并比较指针与指针指向的内容:*q的内容为3*/return0;实际上,一个二维数组名就相当于一个二级指针。例如,inta34;,此时数组a即是一个二级指针,*a指向二维数组的首地址(也就是a0的首地址),*(a+1)指向a1的首地址,*(a+2)指向a2的首地址。*(*(a+0)+1)表示元素a01,*(*(a+i

30、)+j)表示元素aij。案例3:冒泡排序再认识案例3:冒泡排序再认识案例实现算法分析流程图表达代码实现运行结果1.算法分析定义一维数组arr和长度变量n,在第4章“案例2:冒泡排序”的基础上,将打印数组元素、冒泡排序的过程分别用函数来实现,并用指针作为函数的形参。主函数main()在调用二者时,将数组名arr和数组长度n作为实参传递给两个函数。2.流程图表达程序算法流程如图6-11所示。案例3:冒泡排序再认识3.代码实现#include/*标准输入/输出函数头文件*/#include/*system函数头文件*/#defineMAX20/定义一个值/voidbubble_sort(int*p,

31、intn);/*函数声明,指针作形参*/voidprint_array(int*p,intn);/函数声明,指针作形参/intmain()/主程序开始/intarrMAX,n,i;/*定义所需数组及变量*/printf(请输入数组长度(不大于%d):,MAX);scanf(%d,&n);/*输入数组长度*/printf(请输入数组元素(%d个整数,以空格分隔):n,n);for(i=0;in;i+)scanf(%d,&arri);/*依次输入数组的每个元素*/printf(n冒泡排序前:);print_array(arr,n);/*调用显示函数显示排序前的数组,数组名作实参*/案例3:冒泡排序

32、再认识printf(n);bubble_sort(arr,n);/*调用冒泡排序函数进行排序,数组名作实参*/system(pause);/*暂停屏幕,便于观察结果,按任意键退出*/return0;voidbubble_sort(int*p,intn)/*定义冒泡排序函数,指针作形参*/inti,j,temp;for(i=0;in-1;i+)/*外循环控制比较轮数*/for(j=0;j*(p+j+1)/*如果前一个数比后一个相邻数大,则交换位置*/temp=*(p+j);(p+j)=*(p+j+1);*(p+j+1)=temp;案例3:冒泡排序再认识printf(第%d轮排序后:,i+1);/

33、*每一轮比较后,输出比较结果*/print_array(p,n);printf(n);voidprint_array(int*p,intn)/*定义显示数组函数,指针作形参*/inti;for(i=0;is2;差为负,则s1s2;差为0,则s1=s2。案例4:禁用strcpy库函数3.指针数组若一个数组中的所有元素都是指针类型,每一个元素存放的都是一个地址,则这个数组就称指针数组。定义一维指针数组的格式为:数据类型名*数组名数组长度;例如:chars3=zhangsan,lisi,wangwu;定义了一个字符型指针数组s,由于运算符“”的优先级高于“*”,标识符s先与“”结合,表示是一个长度为

34、3的数组,然后与“*”结合,表示数组元素是指针类型,最后char表示数组中每个元素所指向的内存单元存放的是字符型数据,并初始化为三个字符串,即s0存放的是字符串zhangsan的首地址,s1存放的是字符串lisi的首地址,s2存放的是字符串wangwu的首地址。案例4:禁用strcpy库函数上面的示例也可以改写成二维字符数组格式:chars39=zhangsan,lisi,wangwu;使用二维字符数组时,要考虑各个字符串的长度,要找到最长的字符串长度作为二维数组的列,才能存放所有字符串。长度短的字符串势必要剩余部分存储空间,如果字符串很多,显然会浪费存储空间。因此,在C语言中常用字符型指针数

35、组代替二维字符数组,使用效率更高。案例4:禁用strcpy库函数案例4:禁用strcpy库函数案例实现算法分析流程图表达代码实现运行结果1.算法分析第一步:根据案例描述,设计一个主函数main()和一个字符串复制函数mystrcpy。第二步:在主函数中定义两个字符数组str1和str2,一个用于存储已知字符串,一个用于存储复制后的字符串。第三步:在字符串复制函数mystrcpy(char*p,char*q)中,以字符指针作为形参*p、*q,以循环结构逐个字符进行复制,即*p=*q;复制一个字符后,指针自增,以指向下一个待复制的字符。所有字符复制后,在字符数组的最后填充一个字符串结束标志0。第四

36、步:主函数调用mystrcpy函数时,将字符数组名str1、str2作为实参传递。最后打印输出,以检验与输入的字符串是否一致。2.流程图表达程序算法流程如图6-14所示。案例4:禁用strcpy库函数3.代码实现#include/标准输入/输出函数头文件/#include/system函数头文件/#include/gets、puts函数头文件/#defineMAX100/定义数组最大长度值/voidmystrcpy(char*p,char*q);/函数声明/intmain()/主程序开始/案例4:禁用strcpy库函数charstr1MAX,str2MAX;/定义目的数组str1和源数组str

37、2/printf(输入一个字符串(长度不大于%d,以回车键结束):n,MAX);gets(str2);/从键盘向源数组str2中输入字符串/mystrcpy(str1,str2);/调用自定义函数(将字符串从str2复制到str1)/printf(复制后的字符串是:);puts(str1);/输出复制后的字符串/system(“pause”);/暂停屏幕,便于观察结果,按任意键退出/return0;案例4:禁用strcpy库函数voidmystrcpy(charp,charq)/定义复制函数/while(q!=0)/只要字符串不结束,就以单字符方式复制/p=q;/将指针q的字符值赋给指针p指向

38、的单元/p+;/指针自增,指向下一个字符/q+;/指针自增,指向下一个字符/p=0;/字符串复制后,在结尾填充字符串结束标志0*/案例4:禁用strcpy库函数4.运行结果程序运行结果如图6-15所示。案例4:禁用strcpy库函数案例5:指针挑大小使用指向函数的指针与返回指针的函数两种方法实现两个数的比较。案例5:指针挑大小案例描述相关知识指向函数的指针返回指针的函数1.指向函数的指针在C程序中,函数名在编译时被视作该函数所在内存区域的入口地址,该入口地址也被称为函数的指针。因此,可以用一个指针变量指向函数,然后通过该指针调用此函数。通过函数指针实现函数调用的步骤如下。定义指向函数的指针变量

39、,语法格式为:类型名(*函数指针变量名)(形参列表)例如:int(*p)(inta,intb);案例5:指针挑大小(1)两组括号都不能少。int表示被指向函数的返回值的类型。(2)用函数名为指针变量赋值,语法格式为:函数指针变量名=函数名(3)利用指向函数的指针变量调用函数,语法格式为:(*函数指针变量名)(实参列表)注意2.返回指针的函数函数可以返回整型、实型、字符型等类型的数据,还可以返回地址值,即返回指针。返回值为指针的函数称为返回指针的函数,也称指针型函数。指针型函数在动态链表中经常使用。定义指针型函数的语法格式如下。类型名*函数名(形参列表)/*函数体*/return地址;/*返回指

40、针(地址)*/例如:案例5:指针挑大小int*fun()intn=100;return&n;/*返回变量n的地址*/定义了一个函数fun,调用它后可返回一个指向整型数据的指针。但这里有一个安全隐患,即n是函数fun的局部变量,函数调用结束后n的内存空间被撤销(并不是销毁数据,而是程序放弃对它的使用权,其它代码可随意使用这个内存空间),如果该被其它代码占用,即使返回其指针,也不会得到正确的值。因此,在定义返回指针的函数时,形参通常要使用指针,并返回该指针。这样地址来自本函数之外,不再受本函数的影响,安全性得到保障。案例5:指针挑大小案例5:指针挑大小案例实现算法分析流程图表达代码实现运行结果1.

41、算法分析第一步:根据案例描述,设计三个函数:一个主函数main、一个求最大值的函数max(inta,intb)和一个返回指针的求最大值的函数*fun(inta,intb,int*s)。第二步:定义所需变量,a、b用于存储键盘输入,c用于存储最大值,指向max函数的指针*p,存储*fun函数返回值的指针*q。第三步:利用指向函数的指针调用max函数时,先将函数名(入口地址)赋给指针变量p,即p=max;然后调用函数并将返回的最大值赋给变量c,即c=(*p)(a,b);。第四步:利用返回指针的函数求解最大值,直接调用fun函数,将返回的地址赋给指针变量q,即q=fun(a,b,q);然后获取q指向

42、的值(最大值)并赋给变量c,即c=*q;。第五步:将两种函数设计的结果输出,同时输出地址,便于观察。案例5:指针挑大小2.流程图表达程序算法流程如图6-16所示。3.代码实现#include/*标准输入/输出函数的头文件*/#include/*system函数的头文件*/intmax(inta,intb);/*函数声明*/int*fun(int*p1,int*p2);/*函数声明(返回指针的函数)*/intmain()/*主函数开始*/inta,b,c,*q=NULL;/*定义所需变量*/int(*p)(inta,intb);/*定义指向函数的指针p*/printf(输入两个整数(以空格隔开、

43、以回车结束):);案例5:指针挑大小scanf(%d%d,&a,&b);/*输入数据*/p=max;/*将函数max赋值给指针p,p即获取了函数max的入口地址*/c=(*p)(a,b);/*通过指针调用函数获取最大全,效果同调用:c=max(a,b);*/printf(“指向函数的指针”运算结果:a=%db=%dmax=%d(函数入口地址:%x)n,a,b,c,p);q=fun(&a,&b);/*调用函数fun后,返回一个指针赋值给指针变量q*/c=*q;/*取指针q指向的数据(最大值)并赋给c*/printf(“返回指针的函数”运算结果:a=%db=%dmax=%d(函数返回地址:%x)n

44、,a,b,c,q);system(pause);/*暂停屏幕,便于观察结果,按任意键退出*/return0;案例5:指针挑大小/定义函数,以便让指针指向maxintmax(inta,intb)if(ab)returna;/*返回较大者*/elsereturnb;/定义函数,返回一个指针int*fun(int*p1,int*p2)if(*p1*p2)returnp1;/*返回较大者的地址(指针)*/elsereturnp2;案例5:指针挑大小4.运行结果程序运行结果如图6-17所示。案例5:指针挑大小同步训练一、选择题1.若有定义“intx=0,*p=&x;”,则语句“printf(%dn,*p

45、);”的输出结果是()。(C语言二级考试题)A.随机值B.0C.x的地址D.p的地址2.以下定义语句中正确的是()。(C语言二级考试题)A.chara=Ab=B;B.floata=b=10.0;C.inta=10,*b=&a;D.float*a,b=&a;3.以下程序运行后的输出结果是()。(C语言二级考试题)intmain()inta=7,b=8,*p,*q,*r;p=&a;q=&b;r=p;p=q;q=r;printf(%d,%d,%d,%dn,*p,*q,a,b);A.8,7,8,7B.7,8,7,8C.8,7,7,8D.7,8,8,7同步训练4.设有定义“inta,*pA=&a;”,以

46、下scanf语句中能正确为变量a读入数据的是()。(C语言二级考试题)A.scanf(%d,pA);B.scanf(%d,a);C.scanf(%d,&pA);D.scanf(%d,*pA);5.设有定义“intn=0,*p=&n,*q=&p;”,则以下选项中正确的赋值语句是()。(C语言二级考试题)A.p=1;B.*q=2;C.q=p;D.*p=5;同步训练6.以下程序运行后的输出结果是()。(C语言二级考试题)voidfun(char*a,char*b)a=b;(*a)+;intmain()charc1=A,c2=a,*p1,*p2;p1=&c1;p2=&c2;fun(p1,p2);pri

47、ntf(%c%cn,c1,c2);A.AbB.aaC.AaD.Bb同步训练7.若程序中已包含头文件“stdio.h”,以下选项中正确运用指针变量的程序段是()。(C语言二级考试题)A.int*i=NULL;scanf(%d,i);B.float*f=NULL;*f=10.5;C.chart=m,*c=&t;*c=&t;D.long*L;L=0;同步训练8.以下是引用片段:(C语言二级考试题)#inc1udeintmain()printf(%dn,NULL);程序运行后的输出结果是()。A0B.1C.-1D.NULL未定义,出错同步训练9.已定义以下函数:(C语言二级考试题)fun(int*p)

48、return*p;该函数的返回值是()。A.不确定的值B.形参p中存放的值C.形参p所指存储单元中的值D.形参p的地址值同步训练10.以下是引用片段:(C语言二级考试题)intmain()inta=5,*b,*c;c=&b;b=&a;程序在执行了“c=&b;b=&a;”语句后,表达式“*c”的值是()。A.变量a的地址B.变量b中的值C.变量a中的值D.变量b的地址11.以下是引用片段:(C语言二级考试题)intmain()chara,b,c,*d;a=;b=xbc;c=0 xab;d=017;print(%c%c%cn,a,b,c,*d);编译时出现错误,以下叙述中正确的是()。A.程序中只

49、有“a=;”语句不正确B.“b=xbc;”语句不正确C.“d=0127;”语句不正确D.“a=;”和“c=0 xab;”语句都不正确同步训练12.若有以下定义和语句:(C语言二级考试题)#includeinta=4,b=3,*p,*q,*w;p=&a;q=&b;w=q;q=NULL;则以下选项中错误的语句是()。A.*q=0;B.w=p;C.*p=a;D.*p=*w;同步训练13.以下是引用片段:(C语言二级考试题)int*f(int*x,int*y)if(*x*y)returnx;elsereturny;intmain()inta=7,b=8,*p=&a,*q=&b,*r;r=f(p,q);

50、printf(%d,%d,%d,*p,*q,*r);执行后输出结果是()。A.7,8,8B.7,8,7C.8,7,7D.8,7,8同步训练14.若有说明“intn=2,*p=&n,*q=p;”,则以下非法的赋值语句是()。(C语言二级考试题)A.p=q;B.*p=*q;C.n=*q;D.p=n;15.若有说明语句“inta,b,c,*d=&c;”,则能正确地从键盘读入三个整数并分别赋给变量a、b、c的语句是()。(C语言二级考试题)A.scanf(%d%d%d,&a,&b,d);B.scanf(%d%d%d,&a,&b,&d);C.scanf(%d%d%d,a,b,d);D.scanf(%d%

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高中资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁