版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
8.1指针的概念一、变量的地址
计算机中,数据存储在内存中,内存可划分为若干存储单元,每个单元可以存放8位二进制数,即1个字节,每个单元具有唯一的一个地址。(内存区的每一个字节有一个编号,即地址)变量的地址:系统为变量分配的内存单元的地址。(一个无符号的整型数)inta;floatb;a=3;b=5;二、变量的访问方式1)直接访问2)间接访问定义一个变量p,存放a的地址,通过p访问a,若将变量p的值改为3AB8(b的地址),则可通过p访问b。三、指针变量:存放地址的变量如:p为指针变量,它存放整型变量a的首地址,称指针变量p指向整型变量a。8.2指针变量的定义与引用一、定义方法类型符*指针变量名如:int*p1,*p2;char*ps;float*pf;指针变量的类型:所指向的内存中存放的数据的类型。二、指针变量的赋值指针变量的值是地址,是个无符号整数。(不能直接将整型常量赋给指针变量)1)用变量的地址给指针变量赋值(求地址运算符&)变量的类型必须与指针变量的类型相同如:inta,b,*p;p=&a;2)用相同类型的指针变量赋值如:inta;int*p1,*p2;p1=&a;p2=p1;3)赋空值NULLp=NULL;或p=0;指针变量初始化方法:赋空值NULL用已定义的变量的地址int*p1=NULL;floata;float*p2=&a;三、指针变量的应用1)两个运算符:*、&
形式:&任意变量
/*取地址运算符*/
*指针变量
/*指针运算符*/&a表示变量a所占据的内存空间的首地址;*p表示指针变量p所指向的内存中的数据。应用:通过指针变量访问所指变量将指针变量指向被访问的变量如:inta=5,*p,b;p=&a;访问所指变量取内容:b=*p;存内容:*p=100;注意:*p若出现在“=”的右边或其他表达式中则为取内容;*p若出现在“=”的左边为存内容。#include<stdio.h>intmain(){inta=5,b=3;int*p;p=&a;b=*p+5;printf(“%d\n”,b);*p=4;printf(“%d,%d”,a,*p);}104,4例:读程序写结果。#include<stdio.h>intmain(){inta=3,b=5;int*p=&a;printf(“%d\n”,*p);*p=4;p=&b;printf(“%d\n”,*p);*p=6;printf(“%d,%d\n”,a,b);}354,62)运算规则*、&:优先级相同,且右结合,与++、--、!等单目运算符优先级相同。下列表达式的含义:
&*p*&a等价于pa2)运算规则*、&:优先级相同,且右结合,与++、--、!等单目运算符优先级相同。写出下面各表达式的结果,并找出具有等价关系的对子。inta=5,*p=&a;&*p*&a(*p)++&aa*p++*(p++)a++下列表达式的含义:
&*p*&a等价于pa#include<stdio.h>intmain(){inta,b,c;int*pa,*pb,*pc;pa=&a,pb=&b,pc=&c;scanf(“%d%d”,pa,pb);c=a+b;printf(“c=%d\n”,*pc);*pc=a+*pb;printf(“c=%d\n”,c);c=++*pa+(*pb)++;printf(“c=%d\n”,c);}例:交换两个数a、b的值#include<stdio.h>intmain(){inta=5,b=8;intt;printf(“a=%d,b=%d\n”,a,b);t=a;a=b;b=t;printf(“a=%d,b=%d\n”,a,b);}例:交换两个数a、b的值#include<stdio.h>intmain(){inta=5,b=8;intt;int*pa=&a,*pb=&b;printf(“a=%d,b=%d\n”,a,b);t=*pa;*pa=*pb;*pb=t;printf(“a=%d,b=%d\n”,a,b);}指针变量作函数参数例:编写一个函数实现两个数的交换。#include<stdio.h>intswap(intx,inty){intt;t=x;x=y;y=t;}main(){inta=3,b=5;swap(a,b);printf(“%d%d”,a,b);}#include<stdio.h>intswap(int*x,int*y){intt;t=*x;*x=*y;*y=t;}main(){inta=3,b=5;swap(&a,&b);printf(“%d%d”,a,b);}例:输入a,b,c三个数,按大小顺序输出。#include<stdio.h>intswap(int*x,int*y){intt;t=*x;*x=*y;*y=t;}intmain(){inta,b,c;printf(“enterdataa,b,c:”);scanf(“%d%d%d”,&a,&b,&c);if(a<b)swap(&a,&b);if(a<c)swap(&a,&c);
if(b<c)swap(&b,&c);printf(“%d%d,%d”,a,b,c);}8.3指针和数组一、一维数组与指针1)数组是连续存放的若干个元素的集合2)数组名就是指向此数组第1个元素的指针(首地址)如:inta[10],*p;则p=a;等价于p=&a[0];3)某一元素的地址:p=&a[i]
用指针引用该元素:*pa[i]4)数组元素的下标在内部实现时,统一按“基地址+位移”的方式处理,即:aa+1a+i故表示数组元素的地址可用:p+i、a+i
表示数组元素的内容可用:a[i]、*(p+i)、*(a+i)数组名a(数组的指针)与指向数组首地址的指针变量p不同,a不是变量。例:读程序写结果。#include<stdio.h>intmain(){inti,a[5];int*p;for(i=0;i<5;i++){p=&a[i];a[i]=i;printf(“%3d”,*p);}printf(“\n”);}#include<stdio.h>intmain(){inti,a[5];int*p=a;for(i=0;i<5;i++,p++){*p=i;printf(“%3d”,*p);}printf(“\n”);}数组指针、指针变量与数组元素之间的关系:设有inta[10],*p=a;则例:数组的使用intmain(){inti,a[5],*p=a;printf(“Input5numbers:\n”);for(i=0;i<5;i++)scanf(“%d”,&a[i]);printf(“Outputthesenumbers:\n”);for(i=0;i<5;i++)printf(“%d”,a[i]);printf(“\n”);}scanf(“%d”,a+i);scanf(“%d”,p+i);printf(“%d”,*(a+i));printf(“%d”,*(p+i));二、指针的运算1)赋值运算如:p=&x;p=a;p=NULL;2)加减运算如:a+i、p+i(只能用于数组元素的引用,注意下标的有效范围)3)指针相减运算:求两地址的间距如:p-a(两个指针的类型相同,并指向同一连续的存储区域)4)移动指针(++、--)如:p++
(对数组名不能实施该运算)例:将数组a的数据复制到数组b中并输出#include<stdio.h>#defineM7intmain(){inti,a[M]={23,15,50,3,21,20,35},b[M];for(i=0;i<M;i++)b[i]=a[i];printf(“Outputthesenumbers:\n”);for(i=0;i<M;i++)printf(“%d”,b[i]);printf(“\n”);}#include<stdio.h>#defineM7intmain(){inti,a[M]={23,15,50,3,21,20,35},b[M];int*p=a,*q=b;for(i=0;i<M;i++){*q=*p;q++;p++;}printf(“Outputthesenumbers:\n”);for(i=0;i<M;i++)printf(“%d”,b[i]);printf(“\n”);}例:将数组a的数据复制到数组b中并输出#include<stdio.h>#defineM7intmain(){inti,a[M]={23,15,50,3,21,20,35},b[M];for(i=0;i<M;i++)b[i]=a[i];printf(“Outputthesenumbers:\n”);for(i=0;i<M;i++)printf(“%d”,b[i]);printf(“\n”);}#include<stdio.h>#defineM7intmain(){inti,a[M]={23,15,50,3,21,20,35},b[M];int*p=a,*q=b;for(i=0;i<M;i++){*q=*p;q++;p++;}printf(“Outputthesenumbers:\n”);for(i=0;i<M;i++)printf(“%d”,b[i]);printf(“\n”);}printf(“%d”,*q++);三、数组的指针与函数实参例:编写一函数求一维数组的最大元素及其下标位置(要求使用指针)已知:数组首地址p,元素个数n;(作函数参数)结果:下标k;(作返回值)intmax_array(int*p,intn)设最大值放在max中,则初始状态为:
max=*p,k=0如果*(p+i)>max则max=*(p+i)且k=i#include<stdio.h>intmax_array(int*p,intn){intk=0,max=*p,i;for(i=0;i<n;i++)if(*(p+i)>max){max=*(p+i);k=i;}returnk;}intmain(){inta[10]={23,43,52,23,5,22,33,35,96,34};inti,*p=a,k;for(i=0;i<10;i++)printf(“%5d”,*(p+i));k=max_array(a,10);printf(“\nmax=a[%d]=%d\n”,k,*(p+k));}例:编写一函数求一维数组的元素倒置存放。已知:一维数组,元素个数n;结果:倒置后的一维数组函数定义:intinverse(int*p,intn)算法:1、令p指向数组的开始,q指向结束2、交换两单元的内容3、两指针向中间靠拢4、重复上述2和3,直到p>=q#include<stdio.h>intinverse(int*p,intn){int*q,t;q=p+n-1;while(p<q){t=*p;*p=*q;*q=t;p++;q--;}}intmain(){inta[]={1,3,5,7,9};intk,*p;for(p=a,k=0;k<5;k++)printf(“%5d”,*p++);printf(“\n”);inverse(a,5);for(p=a,k=0;k<5;k++)printf(“%5d”,*p++);}四、多维数组与指针
用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。1.多维数组元素的地址可以认为二维数组是“数组的数组”,例:定义inta[3][4]={{1,3,5,7},{2,4,6,8},{9,1,0,1}};则二维数组a是由3个一维数组所组成的。135724689101a[0]a[1]a[2]a此二维数组可以看作三个一维数组
a为二维数组的首地址
a[0]或*a为第一个一维数组的首地址
a[0][0]或*(*a+0)为第一个一维数组的第一个元素135724689101a[0]a[1]a[2]aa[i][j]*(a[i]+j)*(*(a+i)+j)数组元素
a[i]&a[i][0]*(a+i)数组元素地址a+i&a[i]a是二维数组名,不同于一维数组,如:
staticinta[3][4]={{1,3,5,7},{2,4,6,8},{9,1,0,1}};
int*p;可以p=a[0];而p=a错误。不要把&a[i]理解为a[i]单元的物理地址,因为a[i]不是一个变量,&a[i]和a[i]的值是相等的。但含意不一样。前者指向行,后者指向列;
&a[i]:第i行的首地址a[i]:第i行0列地址
&a[i]+1:第i+1行的首地址a[i]+1:第i行1列的地址表示形式含义a
二维数组名,指向一维数组a[0],即0行首地址a[0],*(a+0),*a0行0列元素地址a+1,&a[1]1行首地址a[1],*(a+1)1行0列元素a[1][0]的地址a[1]+2,*(a+1)+2,&a[1][2]1行2列元素a[1][2]的地址*(a[1]+2),*(*(a+1)+2),a[1][2]1行2列元素a[1][2]的值2.指向多维数组元素的指针变量(1)指向数组元素的指针变量例:用指针变量输出二维数组元素的值
#include<stdio.h>intmain(){
inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int*p;
for(p=a[0];p<a[0]+12;p++)
{if((p-a[0])%4==0)
printf(″\n″);
printf(″%4d″,*p);
}}
运行结果如下:1357911131517192123
(2)指向由m个元素组成的一维数组的指针变量例:出二维数组任一行任一列元素的值#include<stdio.h>intmain(){inta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int(*p)[4],i,j;
p=a;
scanf(“i=%d,j=%d”,&i,&j);printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j));}
运行情况如下:i=1,j=2↙a[1,2]=138.4指针与字符串1)C语言中字符串以‘\0’作结束符;2)用字符数组存放字符串;3)字符串指针就是字符数组的首地址。如:chara[]=“Apple”;charb[]={‘C’,’h’,’i’,’n’,’a’,’\0’};一、字符串指针变量定义:char*指针变量如:char*p,*q=“Language”;p=“Thisisabook.”;如:char*p,c[10];p=c;注意:p指向字符串的首地址,不是存放字符串。例:逆序打印字符串算法:设字符串为q;令p指向串尾;打印字符*p,并将p前移,直到p指向串首。#include<stdio.h>intmain(){char*p,*q=“Language”;for(p=q;*p!=‘\0’;)p++;for(p--;p>=q;p--)putchar(*p);putchar(‘\n’);}例:逆序打印字符串算法:设字符串为q;令p指向串尾;打印字符*p,并将p前移,直到p指向串首。#include<stdio.h>intmain(){char*p,*q=“Language”;n=strlen(q);p=q+n;for(p--;p>=q;p--)putchar(*p);putchar(‘\n’);}例:编写一函数判断一个字符串是否回文。(顺读与逆读相同)已知:字符串指针变量p(作参数);结果:是或否算法:1、令q指向最后一个字符2、*p==*q,则两指针向里靠拢,直到p>=q,则return1;否则return0intishuiwen(char*p){char*q=p;while(*q!=‘\0’)q++;q--;while(p<q)if(*p==*q){p++;q--;}elsereturn0;return1;}三、字符数组与字符指针变量比较
chara[]=“Ilovethisgame”,*p=a;1)存储的内容不同字符数组可以存字符串,存的是字符;字符指针变量存的是字符串在内存的首地址。2)赋值方式不同字符数组只能对各个元素赋值;字符指针变量只赋值一次,赋的是地址。如:chara[10],*p;p=“China”;a=“Hello”;(错误)3)当没有赋值时字符数组名代表了一个确切的地址;字符指针变量中的地址是不确定的。如:chara[10],*p;scanf(“%s”,a);scanf(“%s”,p);(错误)4)字符数组名不是变量,不能改变值;字符指针变量可以改变值。如:a++;(错误)p++;8.5指向函数的指针变量
一个函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针。可以定义一个指针变量指向函数,该指针称为指向函数的指针变量。其定义形式如下:例如:int(*p)(int,int);p=max;mainmaxmin定义p为指向函数的指针变量,p指向一个带整型返回值的函数.数据类型(*指针变量名)(参数列表)maxp例:求a和b中的大者。intmain(){intmax(int,int);inta,b,c,(*p)(int,int);
p=max;scanf("%d,%d",&a,&b);c=(*p)(a,b);printf("a=%d,b=%d,max=%d",a,b,c);}注意:对函数指针变量p进行p++,p+n,p--等运算无意义.intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}当每次调用的函数不是固定的时,用指针变量就比较方便。#include<stdio.h>intmain(){inta,b,c,d,(*p)(int,int);a=3,b=5;p=max;c=(*p)(a,b);p=min;d=(*p)(a,b);printf("c=%d,d=%d\n",c,d);}intmax(intx,inty){ returnx>y?x:y;}intmin(intx,inty){ returnx<y?x:y;}intmain(){intmax(int,int),min(int,int),add(int,int);intprocess(intx,inty,int(*fun)(int,int));inta,b;scanf(“%d,%d”,&a,&b);printf(“max=”);process(a,b,max);printf(“min=”);process(a,b,min);printf(“sum=”);process(a,b,add);}例:设一个函数process,在调用它的时候,每次实现不同的功能。输入a,b,分别求a,b中的大数,a,b中的小数和a,b之和。intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}intmin(intx,inty){intz;if(x<y)z=x;elsez=y;return(z);}intadd(intx,inty){intz;z=x+y;return(z);}intprocess(intx,inty,int(*fun)(int,int)){intresult;result=(*fun)(x,y);printf(“%d\n”,result);}例:设一个函数process,在调用它的时候,每次实现不同的功能。输入a,b,分别求a,b中的大数,a,b中的小数和a,b之和。8.6返回指针值的函数一般定义形式为:
类型名*函数名(参数表)例如:int*a(intx,inty);8.6返回指针值的函数一般定义形式为:
类型名*函数名(参数表)例如:int*a(intx,inty);例:有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩。intmain(){staticfloatscore[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};float*search(float(*pointer)[4],intn);float*p;inti,m;scanf("%d",&m);p=search(score,m);for(i=0;i<4;i++)printf("%5.2f\t",*(p+i));}float*search(float(*pointer)[4],intn){float*pt;pt=*(pointer+n);return(pt);}607080905689678834789066pointerpt【例】输入一个字符串和一个字符,如果该字符在已知字符串中,从该字符第一次出现位置开始输出字符串中剩余部分。要求定义如下函数找出该字符第一次出现的位置并返回主函数进行剩余字符串的输出。char*match(char*s,charch){}#include<stdio.h>intmain(){ char*match(char*s,charch); charch,str[20],*p; p=NULL; printf(“请输入字符串”); scanf(“%s”,str); getchar(); printf(“请输入一个字符”); scanf(“%c”,&ch); if((p=match(str,ch))!=NULL) printf(“%s\n”,p); else printf(“字符不在已知字符串中\n”);}char*match(char*s,charch){ while(*s!=’\0’) {if(*s==ch) returns; else s++; }returnNULL;}8.7指针数组和指向指针的指针指针数组的概念
一个数组,其元素均为指针类型数据,称为指针数组。定义形式为:类型名*数组名[数组长度]
例如:int*p[5];char*name[5];name[0]name[1]name[2]name[3]name[4]FollowmebasicgreatWallFORTRANComputerdesign利用指针数组求一维数组的最大值。#include<stdio.h>intmain(){ inta[5]={20,56,80,70,90},i,max; int*p[5];for(i=0;i<=4;i++) p[i]=&a[i]; max=*p[0]; for(i=1;i<=4;i++) if(*p[i]>max) max=*p[i]; printf(“max=%d\n”,max);}intmain(){staticchar*name[]={"followme","basic","greatwall","fortran","computerdesign"};intn=5;sort(name,n);print(name,n);}intsort(char*name[],intn){char*temp;inti,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++)if(strcmp(name[k],name[j])>0)k=j;if(k!=i){temp=name[i];name[i]=name[k];name[k]=temp;}}}intprint(char*name[],intn){inti;for(i=0;i<n;i++)printf(“%s\n”,name[i]);}指向指针的指针定义形式为:类型名**标识符例如:char**p;p=name+2;
name[0]name[1]name[2]name[3]name[4]FollowmebasicgreatWallFORTRANComputerdesignnamename+2pprintf("%o\n",*p);printf("%s\n",*p);结果为?例main(){staticchar*name[]={"Followme","BASIC","
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 工资按时发放民工保障书
- 赠与合同借款租赁问题探讨
- 育苗种子生产合作
- 跑步机预售合同补充协议
- 工程质量保证保函
- 旅游服务合同的合规观察
- 高强度水泥砖供应合同
- 公路工程分包商的劳务
- 品质保证信誉保
- 外贸绿植购销协议
- 燃气有限公司突发环境专项应急预案
- 【课件】供应商现场与质量管理
- 2024年立式碾米机项目可行性研究报告
- 狼疮性脑病的护理
- 2024年全国统一高考英语试卷(新课标Ⅰ卷)含答案
- 2024年认证行业法律法规及认证基础知识 CCAA年度确认 试题与答案
- 花卉学智慧树知到期末考试答案章节答案2024年浙江农林大学暨阳学院
- T∕ACSC 01-2022 辅助生殖医学中心建设标准(高清最新版)
- 企业用工风险评估报告(实操表格)
- 某绿化工程投标文件(DOC91页)(正式版)
- 在全市现代生态渔业现场推进会上的讲话
评论
0/150
提交评论