




已阅读5页,还剩63页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第六章指针,信息学院自动化仪表研究所,C语言程序设计,本章主要内容,指针概述地址指针指针变量多重指针指针变量作为函数参数指针与数组数组、指针与函数调用行指针指针数组指针与函数指向函数的指针变量返回指针值的函数,一、指针概述,1地址(address)P201如果在程序中定义了一个“实体”(变量、数组、函数),编译时系统就要给这些实体分配内存单元。分配规则:,什么是内存单元“地址”?,内存单元是以字节为单位,每个字节都有一个编号(即“地址”)。如果将内存比作一个旅馆,内存单元就好比“床位”,而实体则好比“旅客”。这些“旅客”(实体)中,有单人型(char)、夫妇型(int)、家庭型(float,long,double等),还有团体型(数组等)。每个“实体”占用的内存单元是不同的。如:chara;intb;floatc;intd3;intmax(),内存单元与地址,main()chara;intb;floatc;intd3;intmax();,地址,通常我们关心的不是各个内存单元的具体地址值,而是每个实体的“起始地址”。,如何表示实体地址?,实体地址表示法1:直接访问(实体名)普通变量a,b,cchar*b;float*c;,通常在C语言中,所谓“指针”就是指“指针变量”。从现在开始,我们所说的“指针”除非另加说明,否则均表示“指针变量”。,是不是说地址有”整型”,”字符型”,”实型”之分?,为什么要使用指针变量?,C程序中访问(读写)变量有两种方式:直接访问(按名单预留的座位入座)利用实体名访问变量。访问变量的过程变量(实体)名定义时分配的地址变量值好比“先坐再买票”看电影:来一个观众,分配一个空位给他去坐,并且还要在纸上记一个某人坐在哪里。这种方式对用户来说很方便(“直接就座”),但对系统来说,“找某人”就极不方便(间接:查名字座号)。间接访问(先买票,后按号入座)把变量地址先存放在“指针”中,再通过“指针”访问变量。好比先买票(票指针,座号地址),再“按号入座”看电影。这种方式对用户来说属于“间接就座”,但对系统查找来说就很直接,且便于处理。尤其对于数组(团体),可通过指针简单自加或自减,对整个数组进行处理。,习惯用语:若指针变量p存放了变量a的地址,我们称“p指向a”。,指针变量不要谈”指”色变,指针是C语言学习中的一大难点。难难在概念。,main()inta,*p1,*p2=,学了半天,我还是一头雾水,首先搞定*p,请看以下变量声明语句inta,*p1;charb,*p2;a,b普通变量(存放某个数值或字符)p1,p2指针变量(存放某个实体的地址),如果是int*a,p1;char*b,p2;,变量声明时,如果变量名前带*号,表示该变量是个指针变量,注意不同的*p,以下程序中哪些语句是错误的?main()inta,*p;a=3;p=3;/*或者p=a;*/p=/*或者*p=3*/,讨论:程序中引用变量时,对指针变量p,不带*号引用表示?带*号引用表示?,两个特殊的运算符system(cls);p=,main()int*p,a12=1,2,3,4,5;clrscr();p=a;for(;*p5;p+)printf(%d,*p);,结果:a=13,b=10,结果:1234,p指向字符数组时的*p,如果p被定义成指向某个字符数组或某个字符串的指针变量,则*p代表某个字符。如char*p,a3=”abcd”;p=a;*p代表a中的某个字符,main()char*p,a12=abcde;p=a;for(;*p;p+)printf(%c,*p);,main()char*p;p=abcde;for(;*p;p+)printf(%c,*p);,如果直接用a进行循环,行不行?,在for语句中用*p控制循环,是否适用于数值数组?,p=*int*p;x=3.14;p=,结果:y=-2621.000000,怎么会这样?,把int*p改为float*p后,结果正确:y=3.140000,指针变量能参加运算吗?,指针变量和其他变量一样,可以在各种表达式中参加运算。但指针变量和普通变量不同,只能进行以下三种运算:赋值运算算术运算指针比较,指针变量的赋值运算,指针变量初始化变量声明时赋值,main()inta=5,*p=printf(“%d,%d,%dn”,p,*p,a),指针变量一般赋值程序处理时赋值,结果:2000,5,5,main()intx;int*p1,*p2;p1=%p以16进制显示指针,典型错误,指针变量定义后,未指向具体存储单元(实体地址)就使用,此时指针变量所指单元是任意的,是个”危险指针”。,【例一】若有定义char*p,ch;则不能正确赋值的语句组是:A)p=,【例二】若有定义char*a,b30;则以下各语句正确的是:A)a=”abcde”;B)b=”abcde”;C)scanf(“%s”,a);D)scanf(“%s”,b);,X,X,字符串是一种特殊的实体,存放在内存用户区的常量区。,为什么未指向实体的指针是“危险指针”?,“危险指针”?不要耸人听闻好不好!,一个指针未指向任何实体就被使用,属于”内存盗用”!因为该指针将随意指向内存中某一单元,轻则误取或破坏其他实体的值,重则破坏操作系统的工作。,一个指针变量被声明后,在没有被赋予某个实体地址之前,如果使用它,不仅可能破坏你的程序,而且可能导致计算机操作系统崩溃,出现灾难性的错误。因为它可能指向内存的任何部分。,空指针P256,空指针:int*p;p=NULL;,NULL是什么?在stdio.h中,定义#defineNULL0所以p=NULL;相当于p=0;,内存使用常识:任何C程序的变量在内存中的地址均由操作系统自动分配,不能由编程者通过赋值指定。p=NULL表示p不指向任何变量。内存的低端只供由操作系统使用(相当于政府机关,普通百姓不能使用)。,讨论:以下程序中的*p1,*p2,#includemain()int*p1=NULL,*p2;clrscr();*p1=100;*p2=200;printf(%d,%dn,*p1,*p2);,*p1有确定地址,但未指向任何变量,*p2无确定地址,是“危险指针”,在指针p指向某个实体的地址之前,不可对*p进行赋值。否则可能发生意想不到的错误(p随便指向某个单元)。,指针变量的算术运算,指针只有两种算术运算加、减p+5p+p-1p-注意加减运算是以实体为单位而不是以字节为单位。此外,两个指针变量可以相减。即:如果两个指针变量指向同一数组时,两个指针变量值之差是两个指针之间的元素个数。参见P256。但两个指针变量相加并无实际意义。,以下程序哪个语句执行时会出错?,#includemain()inta10,*p1=a;clrscr();a+;p1+;,X,指针的逻辑比较P257,指针变量指向同一个对象(如数组)的不同单元地址时,才可以进行比较。地址在前者为小。任何指针变量或地址都可以与NULL作相等或不相等的比较。如if(p=NULL),#include#includefun(char*w,intn)chart,*s1,*s2;s1=w;s2=w+n-1;while(s1s2)t=*s1+;*s1=*s2-;*s2=t;,main()char*p;p=1234567;fun(p,strlen(p);puts(p);,结果:1711717,【注意】对*s1+,因*与+同级,且自右至左结合,所以等价于*(s1+),执行时是先做*s1,后做s1+。P215,*p:多重指针(指向指针的指针)P251,对于int*p;定义一个二级指针(指向指针的指针)存放某个指针变量的地址:等效于int*(*p)在引用时,*p是p间接指向的对象的地址。*p是p间接指向的对象的值。,晕!,用一个*声明一个变量pinta=5,*p=使用时p带两个*是a的值(“两重间接取值),p带一个*是a的地址。,看了例子也许会明白的,以下程序段的输出是什么?int*pp,*p,a=20,b=30;pp=,对不对?,结果:30,30(多重间接取值),20,指针变量作为函数参数使用,main()voidswap(int,int);inta=5,b=3,*p1,*p2;clrscr();p1=,main()voidswap(int*,int*);inta=5,b=3,*p1,*p2;clrscr();p1=,结果:x=2,y=10a=5,b=3,结果:x=2,y=10a=2,b=10,再看一个例子,#includefun(int*i)staticinta=1;*i+=a+;main()intk=0;fun(,结果:3第一次调用fun(【讨论】如果fun()函数中没有static,结果呢?,为了实现:在被调函数中改变实体值,然后在主调函数中使用这些改变了的实体值主要技术要点在于:主调函数的实参和被调函数对应的形参都必须用地址表示(地址传递)用于作实参的地址可以是:clrscr();p=a;for(i=0;iN;i+)scanf(%d,Letstry运行程序,观看结果在scanf语句中,分别用a+i、p+i和其中0i10,则对a数组元素不正确的引用是。A)ap-aB)*(int*p,i,j=0;system(cls);p=a0;/*p=a*/*for(i=0;i9;i+)*/printf(%dn,*(a0+1);,Letstry1、将a0改为a1、a2int*p,i;system(cls);p=a0;for(i=0;i3;i+)printf(%d,a+i);printf(%d%d%dn,改成*(a+i)、ai分别试试再把%d改为%p试试,【注意】二维数组中,ai、a+i与*(a+i)等价(P225)。原因:a+i不是变量,C规定ai、a+i与*(a+i)等价(P226)。,看一个例子,#includemain()inta33=1,2,3,4,5,6,7,8,9;int*p,i,j;system(cls);p=a;for(i=0;i3;i+)for(j=0;j3;j+)printf(%d,*(*(a+i)+j);,改成aij试试,用简单指针变量指向二维数组时,用简单指针变量指向二维数组时:inta1010,*p;/*p=a;*/p=a0;p都是列地址性质的指针(姑且称“列指针”)。此时,p可与“排队法”中的a0互换使用,但不能与“行列法”中的a互换使用。,比较一下,#includemain()inta33=1,2,3,4,5,6,7,8,9;int*p,i;system(cls);p=*a;for(i=0;i9;i+)printf(%dn,*(p+i);,123456789,换成*(a0+i)试试,再看下一个例子,#includemain()inta33=1,2,3,4,5,6,7,8,9;int*p,i,j;system(cls);p=a;for(i=0;i3;i+)for(j=0;j3;j+)printf(%d,*(*(a+i)+j);,a改成p试试,【讨论】如果将输出语句中的*(*(a+i)+j)改为*(*(p+i)+j)可不可以?,不行!,Why?!,因为p不是“行指针”!,行指针P229,形式:int(*p)n含义:p为指向含有n个元素的一维数组的指针变量。P255表10.2使用:二维数组可以视为由若干一维数组组成。行指针p是行地址性质的指针。此时,p可与“行列法”中的a互换使用,但不能与“排队法”中的a0互换使用。,行指针是如何使用的?,若inta45;int(*p)5;p=a;则(*p)0=a00;(*p)1=a01;(*p)2=a02;(*(p+1)0=a10;(*(p+1)1=a11;,行指针是一种行地址,可以与二维数组用数组名表示的行地址互换使用。事实上,有(*(p+i)j=pij=*(*(p+i)+j)=aij;,示例一,main()inta33=1,2,3,4,5,6,7,8,9;int(*p)3,i,j;p=a;for(i=0;i3;i+)for(j=0;j3;j+)printf(%d,*(*(p+i)+j);,结果:123456789,示例二,若有以下定义和语句,且0i4,0j3,则不能访问a数组元素的是。inti,(*p)3;inta3=1,2,3,4,5,6,7,8,9,10,11,12;p=a;A)*(*(a+i)+j)B)pijC)(*(p+i)jD)pi+j,答案:D(pi+j是个地址),示例三,main()chara310=abc,123456,ABCDE;char(*p)10;p=a;printf(%s,%sn,p+1,*(p+1);printf(%c,%c,%cn,*(*(p+1),*(*(p+2)+1),(*(p+2)1);,结果:123456,1234561,B,B,示例四,以下程序运行结果是。main()charaa3=a,b,c,d,e,f;char(*p)3=aa;inti;for(i=0;i2;i+)if(i=0)aaii+1=*(p+);printf(%cn,*p);,答案:d,说明行指针p实际上是一个二级指针,*p相当于取行首地址,*p相当于取行首元素的值。因为*和+优先级相同,且均为自右向左结合,所以*(p+)和*p+一样,均表示选取*p值,然后p+(移到下一行)。本程序运行后,数组aa的值为a,a,c,d,e,f,指针与字符串P232,【例一】求以下程序的运行结果。main()char*pc=#Fujian#Province#;while(*pc)while(*pc=#)pc+;if(*pc=0)break;printf(%c,*pc);pc+;printf(n);,结果:FujianProvince,许多字符串操作通常使用指针和指针运算来实现,因为字符串趋向于严格地逐一访问的形式,指针与字符串,【例二】以下函数的功能对应于。intfun(char*s,char*t)while(*s)A)strlen(s)+strlen(t)B)strcmp(s,t)C)strcpy(s,t)D)strcat(s,t),结果:B,多数字符串函数在涉及到循环控制时,均采用与strcmp()函数相似的指针方式。这种方式比使用下标更快,有效且更容易理解。,例三main()char*p1,s80;p1=s;dogets(s);while(*p1)printf(“%c”,*p1+);while(strcmp(s,”done”);,Letstry,指针与字符串,指针数组,定义:char*p5;功能:定义数组p5,其每个元素p0、p1、p4都是指针变量。通常用于指向一组字符串。此时,对于pi,其下标表示第i个字符串,pi本身是第i个字符串的首地址。,示例,main()char*str=AA,BB,CC;str1=str2;printf(%s,%s,%sn,*str,str1,*(str+2);,结果:AA,CC,CC,示例,serror(intnum)staticchar*err=“cannotopenfilen”;“readerrorn”;“writeerrorn”;“mediafailuren”;printf(“%s”,errnum);,指针数组常用于指向出错信息的指针,三、指针与函数,1、指向函数的指针变量P241可以用指针变量指向一个函数。一个函数在编译时被分配给一个“入口地址”。定义方法:类型标识符(*指针变量名)();如int(*p)();指向一个返回整型值的函数用法:设有函数fun(a,b)令p=fun;则有(*p)(a,b)相当于fun(a,b);此时c=(*p)(a,b)与c=fun(a,b)等效。,【例1】求a和b中的大者main()intmax();inta,b,c;scanf(“%d,%d”,改为:main()intmax();int(*p)();inta,b,c;p=max;scanf(“%d,%d”,#include#include#include#includemain()intstrcmp();intnumcmp();chars180,s280;gets(s1);gets(s2);if(isalpha(*s1)check(s1,s2,strcmp);elsecheck(s1,s2,numcmp);,check(char*a,char*b,int(*cmp)()printf(“testingforequalityn”);if(!(*cmp)(a,b)printf(“equal”);elseprintf(“notequal”);numcmp(char*a,char*b)if(atoi(a)=atoi(b)return0;elsereturn1;,例2,三、指针与函数,2、返回指针值的函数P246一般形式int*a(x,y);表示该函数的返回值是一个指针。,例3P246例10.25,main()floatscore4=60,70,80,90,56,89,67,88,34,78,90,66;float*search(float(*pointer)4,intn);float*p;inti,m;printf(“enterthenumberofstudent:”);scanf(“%d”,本章作业,1、所给程序段是把从键盘输入的一行字符作为字符串放在字符数组中,然后输出。请填空。,inti;chars80,*p;for(i=0;i79;i+)si=getchar();if(si=n)break;si=;p=;while(*p)putchar(*p+);,一、填空题,2、下面的函数是求两个整数之和,并通过形参传回结果。intadd(intx,inty,z)=x+y;3、main()inta33=1,2,3,4,5,6,7,8,9,*p;p=a0+2;/*或p=结果:(1)(若将p=a0+2改为p=a+2,结果为(2)_)如果:p=a,输出语句中为*(p+2)呢?(结果:(3)_)如果输出语句中*(a+2)呢?(结
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 前列腺炎的护理与保健
- 复古端午节总结汇报
- 四川省望子成龙学校2026届九年级英语第一学期期末调研试题含解析
- 山东省滨州惠民县联考2026届化学九年级第一学期期中经典模拟试题含解析
- 2026届内蒙古包头市第三十五中学九上化学期中考试模拟试题含解析
- 2025年高中美术教师资格考试面试试题与参考答案
- 2025年导游资格岗位从业基础知识考试题库与答案
- 2025年急救方面面试题目及答案
- 2026届贵州省7月普通高中学化学九上期中调研模拟试题含解析
- 2026届吉林省长春市德惠市大区化学九上期中经典模拟试题含解析
- 部编人教版六年级上册道德与法治全册教案
- 2025年共青团入团考试测试题库及答案
- 第13章第2节 人体免疫课件-2025-2026学年北师大版八年级上册生物
- 2025上海科技馆招聘高层次专业技术人才3人备考考试试题及答案解析
- 线路维护材料管理办法
- 2025年外企面试英语常见问题与答案解析
- 2025年6月浙江省高考物理试卷真题(含答案解析)
- 民宿课程题目大全及答案
- 2025年银行内部审计部门财务审计员竞聘考试指南
- 洗煤厂冬季三防知识培训课件
- 2025西安医学院第一附属医院第二批招聘(42人)考试备考题库及答案解析
评论
0/150
提交评论