C语言程序设计-基于计算思维的培养 课件 第8章 指针_第1页
C语言程序设计-基于计算思维的培养 课件 第8章 指针_第2页
C语言程序设计-基于计算思维的培养 课件 第8章 指针_第3页
C语言程序设计-基于计算思维的培养 课件 第8章 指针_第4页
C语言程序设计-基于计算思维的培养 课件 第8章 指针_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章指针目录/Contents指针概念指针变量的定义和初始化取地址运算符、间接寻址运算符向函数传递指针变量函数指针问题的提出intmain(){inta,b;a=5;b=9;Swap(a,b);printf("a=%d,b=%d",a,b);return0;}voidSwap(intx,inty){inttemp;temp=x;x=y;y=temp;}为什么不工作?【例8.1】演示两个整型变量的值交换。运行结果:(屏幕显示)a=5,b=9指针的概念内存中的每个字节都有唯一的编号(地址)地址是一个十六进制无符号整数其字长一般与主机相同地址按字节编号,按类型分配空间如何读写内存中的数据?只要指明要访问的变量的内存单元地址就可以立即访问到变量所在的存储单元&ascanf("%d",&a);printf("%d",a);#include<stdio.h>intmain(){ inta=1,b=1; charc='A'; printf("a=%d\t,&a=%p\n",a,&a); printf("b=%d\t,&b=%p\n",b,&b); printf("c=%c\t,&c=%p\n",c,&c);}运行结果:(屏幕显示)a=1,&a=000000000062FE4Cb=1,&b=000000000062FE48c=A,&c=000000000062FE47指针的概念【例8.2】

运用取地址运算符&取出变量的地址,并将其显示出来。指针概念间接寻址:通过存放变量地址的变量去访问变量&a如何读写内存中的数据?指针变量的定义和初始化

存放变量的地址需要一种特殊类型的变量

指针(Pointer)类型

指针变量——具有指针类型的变量

变量的指针←→变量的地址

指针变量

指向

变量变量的地址(指针)变量值变量地址存入指针变量指针变量的定义和初始化【例8.3】

定义指针变量并显示它的值。#include<stdio.h>intmain(){ inta=1; floatb=2.1; charc='A'; int*p1; float*p2; char*p3; printf("ais%d,\t&ais%p,\tp1is%p\n",a,&a,p1); printf("bis%.1f,\t&bis%p,\tp2is%p\n",b,&b,p2); printf("cis%c,\t&cis%p,\tp3is%p\n",c,&c,p3); return0;}运行结果:(屏幕显示)ais1,&ais000000000062FE34,p1is0000000000000001bis2.1,&bis000000000062FE30,p2is0000000000000000cisA,&cis000000000062FE2F,p3is0000000000000010指针变量使用之前必须初始化永远不要使用未初始化的指针变量定义了指针变量pa,但pa并未指向a?如果指针指向一个非你控制的内存空间并对该空间进行访问,将可能造成危险指针变量的定义和初始化#include<stdio.h>intmain(){ inta=1; floatb=2.1; charc='A'; int*p1; float*p2; char*p3; p1=&a; p2=&b; p3=&c; printf("ais%d,\t&ais%p,\tp1is%p,\tp1is%p\n",a,&a,p1,&p1); printf("bis%.1f,\t&bis%p,\tp2is%p,\tp2is%p\n",b,&b,p2,&p2); printf("cis%c,\t&cis%p,\tp3is%p,\tp3is%p\n",c,&c,p3,&p3); return0;}指针已经有了名字,类型和值指针变量的定义和初始化#include<stdio.h>intmain(){ inta=1; floatb=2.1; charc='A'; int*p1; float*p2; char*p3; p1=&a; p2=&b; p3=&c; printf("ais%d,\t&ais%p,\tp1is%p,\tp1is%p\n",a,&a,p1,&p1); printf("bis%.1f,\t&bis%p,\tp2is%p,\tp2is%p\n",b,&b,p2,&p2); printf("cis%c,\t&cis%p,\tp3is%p,\tp3is%p\n",c,&c,p3,&p3); return0;}指针变量指向的数据类型称为基类型指针变量只能指向同一基类型的变量间接寻址#include<stdio.h>intmain(){ inta=1; floatb=2.1; charc='A'; int*p1; float*p2; char*p3; p1=&a; p2=&b; p3=&c; printf("ais%d,\t&ais%p,\tp1is%p,\tp1is%p\n",a,&a,p1,&p1); printf("bis%.1f,\t&bis%p,\tp2is%p,\tp2is%p\n",b,&b,p2,&p2); printf("cis%c,\t&cis%p,\tp3is%p,\tp3is%p\n",c,&c,p3,&p3); return0;}【例8.4】

使用指针变量,通过间接寻址显示变量的值。#include<stdio.h>intmain(){ inta=1; floatb=2.1; charc='A'; int*p1; float*p2; char*p3; p1=&a; p2=&b; p3=&c;*p1=5; printf("ais%d,\t&ais%p,\tp1is%p,\tp1is%p\n",a,&a,p1,&p1); printf("bis%.1f,\t&bis%p,\tp2is%p,\tp2is%p\n",b,&b,p2,&p2); printf("cis%c,\t&cis%p,\tp3is%p,\tp3is%p\n",c,&c,p3,&p3); return0;}引用指针所指向的变量的值称为指针的解引用(PointerDereference)间接寻址值传递与地址传递普通变量作函数参数——按值调用,简称值传递不能修改实参的值

形参←

实参变量指针作函数参数——按地址调用,简称地址传递为了修改实参的值,使用:

指针形参←&实参a&apointerparameteraxparameterargument值传递与地址传递#include<stdio.h>voidSwap(inta,intb);intmain(){intx,y;printf("inputtwointegernumbers:");scanf("%d%d",&x,&y);Swap(x,y);printf("%d\t%d\n",x,y);return0;}voidSwap(inta,intb){ inttemp; temp=a; a=b; b=temp;}形参值的改变不会影响对应的实参【例8.5】

用简单变量作为函数形参,实现两个整数的交换。值传递与地址传递#include<stdio.h>voidSwap(int*p1,int*p2);intmain(){ intx,y; printf("inputtwointegernumbers:"); scanf("%d%d",&x,&y); Swap(&x,&y); printf("%d\t%d\n",x,y); return0;}voidSwap(int*p1,int*p2){ inttemp; temp=*p1; *p1=*p2; *p2=temp;}指针变量作函数参数可以修改实参的值值传递与地址传递voidSwap(int*p1,int*p2){inttemp;temp=*p1;*p1=*p2;*p2=temp;}intmain(){intx,y;x=5;y=9;Swap(&x,&y);printf(“x=%d,y=%d",x,y);return0;}

voidSwap(inta,intb){inttemp;temp=a;a=b;b=temp;}intmain(){intx,y;x=5;y=9;Swap(x,y);printf(“x=%d,y=%d",x,y);return0;}程序1程序2主调函数被调函数实参形参结果有何不同?不能工作!为什么?intmain(){

intx,y;x=5;y=9;Swap(x,y);printf(“x=%d,y=%d",x,y);

return0;}voidSwap(inta,intb){

inttemp;temp=a;a=b;b=temp;}55xy实参形参99abxyab55temp9a

和b是内部变量单向值传递主调函数被调函数intmain(){

intx,y;x=5;y=9;Swap(&x,&y);printf(“x=%d,y=%d",x,y);

return0;}voidSwap(int*p1,int*p2){

inttemp;temp=*p1;*p1=*p2;*p2=temp;}&x&x实参形参&y&yp1p2xyp1p25temp5xy995*p1*p2交换的是p1

和p2指向的单元内容主调函数被调函数#include<stdio.h>voidSwap(int*p1,int*p2);intmain(){ intx,y; printf("inputtwointegernumbers:"); scanf("%d%d",&x,&y); Swap(&x,&y); printf("%d\t%d\n",x,y); return0;}voidSwap(int*p1,int*p2){ int*temp; *temp=*p1; *p1=*p2; *p2=*temp;}指针temp未初始化指针temp指向哪里未知对未知单元写操作是危险的永远要清楚:每个指针指向了哪里指针指向的内容是什么不能工作!为什么?值传递与地址传递#include<stdio.h>voidSwap(int*p1,int*p2);intmain(){ intx,y; printf("inputtwointegernumbers:"); scanf("%d%d",&x,&y); Swap(&x,&y); printf("%d\t%d\n",x,y); return0;}voidSwap(int*p1,int*p2){inta; int*temp=&a; *temp=*p1; *p1=*p2; *p2=*temp;}值传递与地址传递#include<stdio.h>voidSwap(int*p1,int*p2);intmain(){ intx,y; printf("inputtwointegernumbers:"); scanf("%d%d",&x,&y); Swap(&x,&y); printf("%d\t%d\n",x,y); return0;}voidSwap(int*p1,int*p2){ int*temp; temp=p1; p1=p2; p2=temp;}指针temp被赋了值但交换的是地址值不是指针指向单元的内容不能工作!为什么?值传递与地址传递指针变量作为函数参数应用举例【例8.6】

试分析下面的程序能否实现从键盘输入某班学生某门课的成绩和学号。输入负数表示输入结束,计算并显示最高分及相应学生的学号。intReadScore(inta[],longnum[]){inti=-1do{i++;printf("Inputstudent'sID&score:\n");scanf("%ld%d",&num[i],&a[i]);}while(num[i]>0&&a[i]>=0);returni;}voidGetMaxScore(inta[],longnum[],intn,intpmaxscore,longpmaxnum){inti;pmaxscore=a[0];pmaxnum=num[0];for(i=0;i<n;i++){if(a[i]>pmaxscore){ pmaxscore=a[i]; pmaxnum=num[i];}}}指针变量作为函数参数应用举例#include<stdio.h>#defineN40intReadScore(inta[],longnum[]);voidGetMaxScore(inta[],longnum[],intn,intpmaxscore,longpmaxnum);intmain(){ intscore[N],n,maxscore; longnum[N],maxnum; n=ReadScore(score,num); GetMaxScore(score,num,n,maxscore,maxnum); printf("maxscore=%d,\tmaxnum=%ld\n",maxscore,maxnum); return0;}真正的原因:普通变量作函数参数按值调用不能在被调函数中改变相应的实参值运行结果:(屏幕显示)Inputstudent'sID&score:123201910186Inputstudent'sID&score:123201910290Inputstudent'sID&score:123201910375Inputstudent'sID&score:123201910469Inputstudent'sID&score:-1-1maxscore=1,maxnum=0不工作!为什么?指针变量作为函数参数应用举例#include<stdio.h>#defineN40intReadScore(inta[],longnum[]);voidGetMaxScore(inta[],longnum[],intn,int*pmaxscore,long*pmaxnum);intmain(){ intscore[N],n,maxscore; longnum[N],maxnum; n=ReadScore(score,num); GetMaxScore(score,num,n,&maxscore,&maxnum); printf("maxscore=%d,\tmaxnum=%ld\n",maxscore,maxnum); return0;}voidGetMaxScore(inta[],longnum[],intn,int*pmaxscore,long*pmaxnum){ inti; *pmaxscore=a[0]; *pmaxnum=num[0]; for(i=0;i<n;i++) { if(a[i]>*pmaxscore) { *pmaxscore=a[i]; *pmaxnum=num[i]; } }}运行结果:(屏幕显示)Inputstudent'sID&score:123201910189Inputstudent'sID&score:123201910295Inputstudent'sID&score:-1-1maxscore=95,maxnum=1232019102正常工作!指针变量作为函数参数应用举例【例8.7】

假设有一种球类比赛,它的比赛规则如下:①这是一种双人比赛:包括球员A和B,采用回合制。②开始时一方发球,直至判分,接下来胜者发球。③球员只能在获得发球权后得分,得15分胜1场。编写程序,试根据球员的能力值分析n场比赛的胜负次数。指针变量作为函数参数应用举例指针变量作为函数参数应用举例voidPrintInfo();/*函数功能:输出程序信息

函数参数:无

函数返回值:无*/voidGetInputs(float*a,float*b,int*n);/*函数功能:输入能力值

函数参数:指向球员能力值的指针a和b,指向比赛场数的指针n

函数返回值:无*/voidSimNGames(float*proA,float*proB,int*scoreA,int*scoreB,int*winA,int*winB,intn);/*函数功能:模拟n场比赛

函数参数:指向球员能力值的指针proA和proB,指向球员得分的指针scoreA和scoreB,指向球员胜负局数的指针winA和winB,比赛场数n

函数返回值:无*/voidPrintSummary(float*proA,float*proB,int*scoreA,int*scoreB);/*函数功能:输出比赛结果

函数参数:指向球员能力值指针proA和proB,指向球员得分的指针scoreA和scoreB

函数返回值:无*/指针变量作为函数参数应用举例#include<stdio.h>#include<stdlib.h>#include<time.h>intmain(){intn=0;intscoreA=0,scoreB=0,winA=0,winB=0;floatproA,proB;srand(time(0));PrintInfo(); /*输出程序信息*/GetInputs(&proA,&proB,&n); /*输入能力值*/SimNGames(&proA,&proB,&scoreA,&scoreB,&winA,&winB,n);/*模拟n场比赛*/PrintSummary(winA,winB,n);/*输出比赛结果*/return0;}指针变量作为函数参数应用举例指针变量作为函数参数应用举例voidSimNGames(float*proA,float*proB,int*scoreA,int*scoreB,int*winA,int*winB,intn){ for(i=0;i<n;i++)/*n是比赛场数*/ {

模拟1场比赛;

若球员A的得分超过球员B的得分

则A胜1场;

否则 B胜1场; }}voidSimOneGame(float*proA,float*proB,int*scoreA,int*scoreB);{

假设开始时发球方为A; while(!比赛结束) {

若发球方为A

若比赛局面形势小于A的能力值,则 A得1分;

否则 B获得发球权;

否则

若发球方为B

若比赛局面形势小于B的能力值,则 B得1分;

否则 A获得发球权; }}指针变量作为函数参数应用举例intGameOver(int*scoreA,int*scoreB){

若球员A获得15分或球员B获得15分,则

本场比赛结束;

否则

本场比赛没有结束;}指针变量作为函数参数应用举例voidSimNGames(float*proA,float*proB,int*scoreA,int*scoreB,int*winA,int*winB,intn){ for(i=0;i<n;i++)/*n是比赛场数*/ { SimOneGame(proA,proB,scoreA,scoreB); /*模拟1场比赛*/ if(*scoreA>*scoreB) *winA+=1; else *winB+=1; }}指针变量作为函数参数应用举例voidSimOneGame(float*proA,float*proB,int*scoreA,int*scoreB){charserving='A';/*假设开始时发球方为A*/while(!GameOver(scoreA,scoreB)){/*1球比赛*/if(serving=='A')if(rand()/(RAND_MAX+1.0)<(*proA)) *scoreA+=1;else serving='B';elseif(serving=='B')if(rand()/(RAND_MAX+1.0)<(*proB)) *scoreB+=1; else serving='A';}}intGameOver(int*scoreA,int*scoreB){ if(*scoreA==15||*scoreB==15) return1; else return0;}指针变量作为函数参数应用举例voidPrintInfo(){printf("这个程序模拟两个球员A和B的某种球类比赛\n");printf("程序运行需要A和B的能力值(以0~1之间的小数表示)\n");}voidGetInputs(float*a,float*b,int*n){ printf("请输入球员A的能力值(0~1):"); scanf("%f",a); printf("请输入球员B的能力值(0~1):"); scanf("%f",b); printf("请输入模拟比赛的场次:"); scanf("%d",n);}voidPrintSummary(intwinA,intwinB,intn){n=winA+winB;printf("分析开始,共模拟%d场比赛\n",n);printf("球员A获胜%d场比赛,占比%.1f\n",winA,1.0*winA/n);printf("球员B获胜%d场比赛,占比%.1f\n",winB,1.0*winB/n);}指针变量作为函数参数应用举例函数指针及其应用函数指针(FunctionPointers)就是指向函数的指针(PointertoaFunction)格式:数据类型(*指针名)(形参列表);例如:有函数原型:floatFunc(floatx,floaty);则可以定义函数指针float(*p)(float,float);令p=Func;则表示函数指针指向函数Func()。编译器将不带()的函数名解释为该函数的入口地址指向函数的指针变量存储的是函数在内存中的入口地址函数指针及其应用如果有函数原型:char*Func(char*ch1,char*ch2);则可以定义函数指针char*(*p)(char*,char*);令p=Func;则表示函数指针指向函数Func()。若定义函数指针的参数类型与它指向的函数的参数类型不一致,则程序在编译时会出错

char*(*p)(char,char);函数指针及其应用常见错误:忘记了前一个(),写成int*p();/*声明一个函数名为p、返回值是整型指针的函数*/忘掉了后一个(),写成int(*p);

/*定义了一个整型指针*/定义时后一个括号内的参数类型与指向的函数参数类型不匹配函数指针及其应用运行结果:(屏幕显示)pleaseinputtwonumbers:25pleasechoose1or2:1max=5pleaseinputtwonumbers:25pleasechoose1or2:2min=2函数指针函数调用【例8.8】

输入两个整数,然后让用户选择1或2:选择1,调用Max(),输出二者中的较大数;选择2,调用Min(),输出二者中的较小数。函数指针初始化函数指针及其应用intMin(inta,intb){ intz; if(a<b) { z=a; } else { z=b; } returnz }intMax(inta,intb){ intz; if(a

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论