《C语言程序设计经典教程cla》由会员分享,可在线阅读,更多相关《C语言程序设计经典教程cla(24页珍藏版)》请在金锄头文库上搜索。
1、第八章第八章 指针指针n主要内容主要内容p8.1 8.1 指针和指针变量指针和指针变量p8.2 8.2 指针与数组指针与数组p8.3 8.3 字符串的指针字符串的指针n重点重点p熟练掌握指针的定义和引用;掌握用指熟练掌握指针的定义和引用;掌握用指针来处理数组;掌握用指针来处理字符。针来处理数组;掌握用指针来处理字符。A直接直接BA间接间接预备知识预备知识n直接和间接的含义直接和间接的含义n内存内存p即内部存储器,是由内存单元组成即内部存储器,是由内存单元组成pp特点特点特点特点存储单元的最小单位为字节存储单元的最小单位为字节存储单元是线性连续的存储单元是线性连续的n内存内存p计算机的内存中的每
2、一个字节都有一个编号计算机的内存中的每一个字节都有一个编号每每一内存单元具有唯一的内存地址一内存单元具有唯一的内存地址系统为每一个已定义的变量分配一定存储空间系统为每一个已定义的变量分配一定存储空间 使变量名与内存的一个地址相对应使变量名与内存的一个地址相对应通过地址就能够访问该地址所标识的存储单元通过地址就能够访问该地址所标识的存储单元u程序处理过程程序处理过程根据地址取出变量所对应的内存单元中存放的值根据地址取出变量所对应的内存单元中存放的值参与计算参与计算/操作操作处理结果存入相应的变量名所对应的内存单元处理结果存入相应的变量名所对应的内存单元 0 1 2 3 0 1 2 3 2000
3、2000地址地址4545变量内容变量内容n高级语言中的变量具有三个属性高级语言中的变量具有三个属性 p变量的名变量的名p变量的值变量的值p变量的地址变量的地址n编程者使用编程者使用c程序的一个变量程序的一个变量p定义变量的数据类型定义变量的数据类型数据类型决定了一个变量在内存中所占用的存储空间的大小数据类型决定了一个变量在内存中所占用的存储空间的大小变量在内存中总是占用几个连续的字节变量在内存中总是占用几个连续的字节p定义变量名定义变量名语言的编译系统会根据变量的数据类型为该变量分配内存单元语言的编译系统会根据变量的数据类型为该变量分配内存单元p确定变量的地址确定变量的地址变量的地址就是为变量
4、分配的内存单元的起始编号变量的地址就是为变量分配的内存单元的起始编号p通过变量名对内存中变量对应的地址进行操作通过变量名对内存中变量对应的地址进行操作C语言如何处理?语言如何处理?指针的概念指针的概念 int a,b,c;a=10;b=20;c=a+b; 100010001002100210041004内存内存内存内存a ab bc c101020203030正常解释正常解释实际情况实际情况100010001002100210041004内存内存内存内存变量名变量名 内存单元的起始地址内存单元的起始地址 长度长度内存地址与变量对照表内存地址与变量对照表 a ab bc c100010002 2
5、100210022 2100410042 210 20101020203030在使用变量时总在使用变量时总要去查表,降低要去查表,降低了运行效率,也了运行效率,也颇感不便。颇感不便。 解决方案解决方案p p10001000这是变量这是变量a的地址的地址这是变量这是变量,存存放的是变量放的是变量a的地址的地址指针变量。指针变量。8.1 指针和指针变量指针和指针变量指针变量的定义指针变量的定义n一般形式为:一般形式为:类型符类型符 *指针变量名指针变量名;如:如:int *p; int *q,*r; float a,*b; char *s1,s2;np、q、r、b、s1均为指针变量;均为指针变量;
6、a、s2为为普通变量。普通变量。n约定:约定:p指针变量的图形表示,如:指针变量的图形表示,如:int *p;p普通变量的图形表示,如:普通变量的图形表示,如:int a; p pa a指针变量的引用指针变量的引用n两种基本的指针运算:两种基本的指针运算:1.&:取变量的地址:取变量的地址2.* :指针运算符(或称:指针运算符(或称“间接访问间接访问”运算符)运算符)如如: int a=10,*p; p=&a; printf(“%d,%d”,a,*p);n输出:输出:10,10 10p pa a&a&a直接访问直接访问间接访问间接访问例例8.1 通过指针变量存取变量的值。通过指针变量存取变量的
7、值。main()int a,b;int *p1,*p2; printf(“a=%d,b=%dn”,a,b); printf(“*p1=%d,*p2=%dn”,*p1,*p2); a=10; b=20;a=10; b=20;p1=&a; p2=&b;p1=&a; p2=&b;p1=&a; p2=&b;p1=&a; p2=&b;a=10; b=20;a=10; b=20;程序程序1程序程序2程序程序3程序程序4p1=&a; p2=&b;p1=&a; p2=&b;*p1=10; *p2=20;*p1=10; *p2=20;*p1=10; *p2=20;*p1=10; *p2=20;p1=&a; p2
8、=&b;p1=&a; p2=&b;a ab b p1p1 p2p210102020&a&a&b&b10102020&a&a&b&b10102020&a&a&b&b?! 使用指针之前,一定要使指针有明确指向。使用指针之前,一定要使指针有明确指向。! 指针变量未存储确定地址时,不能使用,指针变量未存储确定地址时,不能使用, 否则会造否则会造 成系统的崩溃!成系统的崩溃!例例8.2 输入输入a和和b两个数,按先大后小的顺序两个数,按先大后小的顺序输出,输出,a和和b的值不变。的值不变。main() int a,b,*p1,*p2,*p;scanf(“%d,%d”,&a,&b); p1=&a; p2=
9、&b;if(ab) p=p1; p1=p2; p2=p; printf(“a=%d,b=%dt”,a,b);printf(“Max=%d,Min=%dn”,*p1,*p2); a ab b p1p1 p2p2 p p10102020&a&a&b&b&a&a&b&b&a&a输出:输出:输出:输出:a=10,b=20a=10,b=20Max=20,Min=10Max=20,Min=106.2 指针与数组指针与数组 指针与数组的关系指针与数组的关系n一个变量有地址,一个数组元素包含若干一个变量有地址,一个数组元素包含若干个数组元素,每个数组元素都在内存中占个数组元素,每个数组元素都在内存中占用存储单
10、元,它们都有相应的地址,这个用存储单元,它们都有相应的地址,这个地址就可以用指针来实现存储。地址就可以用指针来实现存储。如有:如有:int a5;int *p,*q; p=&a0;q=&a2;*p=5;*q=8;a0a0a1a1a2a2a3a3a4a4p p q q&a0&a0&a2&a25 58 8nC语言规定:语言规定:p数组名代表数组的首地址,也就是第一数组名代表数组的首地址,也就是第一个元素个元素a0的地址。因此:的地址。因此: a &a0。若:若:p=a;/* 或写成或写成p=&a0; */则:则: p+1 &a1 *(p+1) a1 p+i &ai *(p+i) ain实际上,实际
11、上,C语言编译语言编译系统在处理下标变量系统在处理下标变量时,要把它转换成地时,要把它转换成地址法的形式。址法的形式。 p+1指向数组的下一个元素指向数组的下一个元素 a0a0a1a1a2a2a3a3a4a4a ap pp+1p+1ai ai *(a+i) *(a+i)*(p+i)*(p+i) pi pin引用一个数组元素,可以用下标法或指针法。引用一个数组元素,可以用下标法或指针法。p通过数组的起始地址计算数组元素的地址,即通过数组的起始地址计算数组元素的地址,即*(a+i)或或*(p+i)形式。形式。p用指针变量处理数组元素,即用指针变量处理数组元素,即p+形式:形式: main() in
12、t a5=3,8,9,2,6,i,*p;p=a;for(i=0;i5;i+)printf(“%d “,*p); p+; 3 8 9 2 6 3 8 9 2 6a ap pi i 0 0输出结果输出结果输出结果输出结果: 3: 3 1 1 8 8 2 2 9 9 3 3 2 2 4 4 6 6 5 5 printf(“%d “,*p+);n指针和数组的可替代性指针和数组的可替代性pC语言中的指针和数组几乎可以互换语言中的指针和数组几乎可以互换指针可以用来完成涉及数组下标的操作指针可以用来完成涉及数组下标的操作例如:例如:int a10;int *p; 若若若若p=&a0p=&a0;或;或;或;或
13、 p=ap=a;则则p就指向了数组就指向了数组a的首址的首址当当p指向了一维数组指向了一维数组a,指针对数组元素可以表示:,指针对数组元素可以表示:p+n与与a+n ( n(偏移量偏移量)的取值为的取值为09)表示数组元素表示数组元素an的地址,即的地址,即&an *(p+n)和和*(a+n) 表示数组元素表示数组元素an ( n的取值为的取值为09 ) 指向数组的指针变量也可以用数组的下标形式指向数组的指针变量也可以用数组的下标形式pn,其效果相当于,其效果相当于*(p+n),等价于,等价于ann 指针的运算指针的运算p提示提示数组名代表数组的首地址数组名代表数组的首地址固定的,不允许修改的
14、固定的,不允许修改的不能对数组名采用不能对数组名采用 +/-操作操作指针的算术运算除了应用于数组外没有什么意义指针的算术运算除了应用于数组外没有什么意义除数组外,不能认为两个数据类型相同的变量在内存中是除数组外,不能认为两个数据类型相同的变量在内存中是连续存储的连续存储的指针的运算与其基类型有关指针的运算与其基类型有关通常情况下允许一个指针或多个指针指向同一个目标通常情况下允许一个指针或多个指针指向同一个目标p常见错误常见错误对不指向数组的指针进行算术运算对不指向数组的指针进行算术运算将不是指向同一个数组的两个指针相减或比较,这是没将不是指向同一个数组的两个指针相减或比较,这是没有意义的有意义
15、的指针的运算结果超出的数组的范围指针的运算结果超出的数组的范围8.3 指针与字符串指针与字符串 字符串的表示形式字符串的表示形式如如:char str80=“China”;char *p=str;printf(“%s”,str);printf(“%s”,p); printf(“%s”,”China”); n用用%s输入输入/输出字符串时输出字符串时,只需要知道字符只需要知道字符串的开始地址即可。串的开始地址即可。n使使p指向字符串的开始地址,可写成:指向字符串的开始地址,可写成:char *p=”China”; 输出结果均为输出结果均为: Chinan 提示提示p赋值时,字符串的结束标志赋值时
16、,字符串的结束标志0是系统自动增加是系统自动增加的的p在输出或处理字符串指针变量和由字符数组组成的在输出或处理字符串指针变量和由字符数组组成的字符串时只要指出指针变量或字符数组的名字字符串时只要指出指针变量或字符数组的名字对于其它类型的数组,不能只使用数组名输出或处理全对于其它类型的数组,不能只使用数组名输出或处理全部元素部元素p使用指针编写的字符串处理程序比使用数组方式处使用指针编写的字符串处理程序比使用数组方式处理字符串的程序更简洁、更方便理字符串的程序更简洁、更方便在在C语言中,大量使用指针对字符串进行各种处理语言中,大量使用指针对字符串进行各种处理在处理字符串的函数中,一般都使用字符指
17、针作为形参在处理字符串的函数中,一般都使用字符指针作为形参在函数之间通过指针传递整个数组,在被调用函数的内在函数之间通过指针传递整个数组,在被调用函数的内部就可以用指针方式访问数组中的元素部就可以用指针方式访问数组中的元素例例8.3 测定字符串的长度测定字符串的长度main() char str =”abc”,*p;int len;p=str;for(len=0; *p != 0;len+)p+;printf(“%s的长度为的长度为%dn”,str,len); n运行结果:运行结果:abc的长度为的长度为3n思考:思考:abc 0strp plenlen 0 0 1 1 2 2 3 3 不是不
18、是0不是不是0不是不是0是是0for(len=0;*p;len+)p+;printf(“%s的长度为的长度为%dn”,p,len);for(len=0;*p+;len+);123不行,因为不行,因为p已经指已经指向字符串最后。向字符串最后。可以,因为:可以,因为:*p与与*p!=0等价等价可以,因为:可以,因为:*p+是先取是先取*p指指向的内容完成比较,再使向的内容完成比较,再使p+字符指针数组字符指针数组n例例8.4将若干字符串输出将若干字符串输出main()char *str =“Word”,”Excel”,”Outlook”;int i;for(i=0;istr2)B、if (strc
19、mp(str1, str2)C、if (strcmp(str2, str1)0)D、if (strcmp(str1, str2)0)5. 若有语句:若有语句:char s110, s210=“books”,则能将字符串则能将字符串books赋给数组赋给数组s1的正确语句是的正确语句是A、s1=books;B、strcpy(s1, s2);C、s1=s2; D、strcpy(s2, s1);6. 下面程序中有错误的行是下面程序中有错误的行是1、 main( )2、 3、 int x3=1;4、 int k;5、 scanf(%d, &x);6、 for (k=1; k3; k+)7、 x0=x0+xi;8、 printf(x0=%dn, x0);9、 A、3 B、6 C、7 D、57. 下面程序的功能是输出两个字符串中较短串的长度。下面程序的功能是输出两个字符串中较短串的长度。请填空。请填空。#include main( ) char str120, str220;int i, k, num;gets(str1); gets(str2);i=strlen(str1); k=strlen(str2);num=? : ;printf(%dn, num);