《高级语言程序设计:chap06-指针初步》由会员分享,可在线阅读,更多相关《高级语言程序设计:chap06-指针初步(41页珍藏版)》请在金锄头文库上搜索。
1、Chap6指针指针6.1寻找保险箱密码寻找保险箱密码指针基本概念指针基本概念6.2使用指针访问数组元素使用指针访问数组元素6.3字符指针字符指针加密问题加密问题本章要点本章要点n变量、内存单元和地址之间是什么关系?变量、内存单元和地址之间是什么关系?n如何定义指针变量,怎样才能使用指针变量如何定义指针变量,怎样才能使用指针变量?n什么是指针变量的初始化?什么是指针变量的初始化?n指针变量的基本运算有哪些?如何使用指针指针变量的基本运算有哪些?如何使用指针操作所指向的变量?操作所指向的变量?6.1寻找保险箱密码寻找保险箱密码一个关于特工一个关于特工008008寻找保险箱密码的故事寻找保险箱密码的
2、故事关键点分析关键点分析n得到线索:得到线索:02170217单元的单元的“虎跑号虎跑号”寄存箱寄存箱 n提示地址:提示地址:19761976单元单元n找到目标:找到目标:“龙井号龙井号”寄存箱寄存箱n取出内容:取出内容:9119116.1寻找密码的途径分析寻找密码的途径分析n密码密码911911存放在某个寄存箱内,如果我们存放在某个寄存箱内,如果我们知道这个寄存箱的名字,就能够找到密码知道这个寄存箱的名字,就能够找到密码 n如果不知道密码所在的寄存箱名字,知道如果不知道密码所在的寄存箱名字,知道该寄存箱的地址也照样能够取出密码该寄存箱的地址也照样能够取出密码 n如果寄存箱的地址也不知道,但是
3、有另外如果寄存箱的地址也不知道,但是有另外一个地方存放这个寄存箱的地址,就能顺一个地方存放这个寄存箱的地址,就能顺藤摸瓜,间接找到密码藤摸瓜,间接找到密码6.1密码存放示意图密码存放示意图龙井号龙井号9111976虎跑号虎跑号19760217名字名字虎跑号虎跑号龙井号龙井号地址地址02171976内容内容1976911例例6-1利用指针模拟寻找保险箱利用指针模拟寻找保险箱密码的过程密码的过程获取密码的两种方法获取密码的两种方法intmain(void) intkey=911;/*变量变量key存放密码存放密码*/int*addr=NULL;/*变量变量addr存放地址存放地址*/addr=&k
4、ey;/*将将key的地址赋给的地址赋给addr*/*通过变量通过变量key输出密码值输出密码值*/printf(Thekeyis:%dn,key);/*通过变量通过变量key的地址来输出密码值的地址来输出密码值*/printf(IfIknowtheaddressofthekey,Ialsocangetit:%dn,*addr);return0;Thekeyis:911IfIknowtheaddressofthekey,Ialsocangetit:9110X0012FF78指针变量p1550X0012FF78100X0012FF70550X0012FF78每格代表4个字节int *p1;int
5、 n = 55;int *p2;int m = 10;p1 = &n;p2 = &m;0X0012FF700X0012FF740X0012FF780X0012FF7Cmp1p2n*p1的值为55,*p2的值为10问,执行 *p1 = 100;会产生什么影响?指针与存储单元关系图示指针与存储单元关系图示6.1.2地址和指针地址和指针指针指针的的概念概念intm=10,n=55;printf(%d,m;)直接访问直接访问:通过变量名访问:通过变量名访问间接访问间接访问:通过通过另一个变量访问另一个变量访问把变量的地址放到另一变量中把变量的地址放到另一变量中使用时先找到后者使用时先找到后者再再从中取
6、出前者的地址从中取出前者的地址指针变量指针变量:存放地址的变量:存放地址的变量int*p1=&n;printf(%d,*p;)指针变量所指向的变量的类型指针变量所指向的变量的类型int*p;p是整型指针,指向整型变量是整型指针,指向整型变量float*fp;fp是浮点型指针,指向浮点型变量是浮点型指针,指向浮点型变量char*cp;cp是字符型指针,指向字符型变量是字符型指针,指向字符型变量类型名类型名*指针变量名指针变量名指针声明符指针声明符6.1.3指针变量的定义指针变量的定义指针变量的定义指针变量的定义类型名类型名*指针变量名指针变量名int*p;指针变量名是指针变量名是p,不是不是*p
7、*是指针声明符是指针声明符intk,*p1,*p2;等价于:等价于:intk;int*p1;int*p2;6.1.4指针的基本运算指针的基本运算*间接访问运算符间接访问运算符,访问指针所指向的变量的值访问指针所指向的变量的值*p:指针变量指针变量p所所指向的指向的变量变量的值的值a3&ap*p如果指针的值是某个变量的地址,通过指针就如果指针的值是某个变量的地址,通过指针就能能间接访问间接访问那个变量。那个变量。1、取地址运算和间接访问运算、取地址运算和间接访问运算&取地址运算符取地址运算符,给出变量的地址给出变量的地址int*p,a=3;p=&a;把把a的地址赋给的地址赋给p,即即p指向指向a
8、指针变量的类型和它所指向变量的类型相同指针变量的类型和它所指向变量的类型相同#includeintmain(void)inta=3,*p;p=&a;printf(“a=%d,*p=%dn”,a,*p);*p=10;printf(a=%d,*p=%dn,a,*p);printf(Entera:);scanf(%d,&a);printf(a=%d,*p=%dn,a,*p);(*p)+;printf(a=%d,*p=%dn,a,*p);return0;例例6-2取地址运算和间接访问运算取地址运算和间接访问运算a3&ap*pa=3,*p=3a=10,*p=10Entera:5a=5,*p=5a=6,*
9、p=6a3&ap*p(1)当当p=&a后,后,*p与与a相同相同(2)int*p;定义定义指针指针变量变量p*p=10;指针指针p所指所指向向的变量的变量,即即a(3)&*p与与&a相同,相同,是是地址地址*&a与与a相同,相同,是是变量变量(4)(*p)+等价于等价于a+将将p所指所指向向的变量值加的变量值加1*p+等价于等价于*(p+)先取先取*p,然后然后p自加,自加,此时此时p不再指向不再指向a说明说明inta=1,x,*p;p=&a;x=*p+;东1宿舍楼东2宿舍楼东2宿舍楼东4宿舍楼东1宿舍楼1层东1宿舍楼2层东2宿舍楼3层东2宿舍楼1层东1宿101东1宿102东1宿501东1宿5
10、10东1宿101-1床东1宿101-2床东1宿101-1床东3宿501-2床主校区东校区分析各类位移的区别结论结论1:地址是有类型,有层次的:地址是有类型,有层次的变1变1变2变1变9变1变x结论结论2:空间变换的绝对位移距离与:空间变换的绝对位移距离与地址的类型有关地址的类型有关变1变2例例:voidmain()chararr4=a,b,c,d;char*p;p=arr;for(inti=0;i4;i+)printf(“%c”,*p);p+;abcdarrpppp例例:voidmain()intarr4=10,20,30,40;int*p;p=arr;for(inti=0;i4;i+)pri
11、ntf(“%d”,*p);p+;10203040arrppppb2&bp2*p2a1&ap1*p121#includeintmain(void)inta=1,b=2,t;int*p1,*p2;p1=&a;p2=&b;printf(a=%d,b=%d,*p1=%d,*p2=%dn,a,b,*p1,*p2);t=*p1;*p1=*p2;*p2=t;printf(a=%d,b=%d,*p1=%d,*p2=%dn,a,b,*p1,*p2);return0;例例6-3通过通过指针指针改变改变变量的值变量的值a=1,b=2,*p1=1,*p2=2a=2,b=1,*p1=2,*p2=12、赋值运算、赋值运算
12、a3&ap1&ap2*p1*p2inta=3,*p1,*p2;p1=&a;把把a的地址赋给的地址赋给p1,即即p1指向指向ap2=p1;p2也指向也指向a相同类型的指针才能相互赋值相同类型的指针才能相互赋值b4&bp2*p2a2&ap1*p16c&a&c例例6-4指针指针赋值赋值intmain(void)inta,b,c,*p1,*p2;a=2;b=4;c=6;p1=&a;p2=&b;printf(a=%d,b=%d,c=%d,*p1=%d,*p2=%dn,a,b,c,*p1,*p2);p2=p1;p1=&c;printf(a=%d,b=%d,c=%d,*p1=%d,*p2=%dn,a,b,c
13、,*p1,*p2);return0;*p2*p1a=2;b=4;c=6;*p1=2,*p2=4a=2;b=4;c=6;*p1=6,*p2=2例例6-5intmain(void)inta=1,b=2;int*p1=&a,*p2=&b,*pt;printf(a=%d,b=%d,*p1=%d,*p2=%dn,a,b,*p1,*p2);pt=p1;p1=p2;p2=pt;printf(“a=%d,b=%d,*p1=%d,*p2=%dn”,a,b,*p1,*p2);return0;6.1.5指针指针变量变量的的初始化初始化p1b2&bp2*p2a1&a*p1ptb2&ap2*p1a1&bp1*p2pt&
14、aa=1;b=2;*p1=1,*p2=2a=1;b=2;*p1=2,*p2=1对指针的操作对指针的操作/对指针所指向变量的操作对指针所指向变量的操作*p1和和*p2的值都由的值都由1和和2变成了变成了2和和1(1)直接改变指针的值直接改变指针的值(2)改变指针所指变量的值改变指针所指变量的值p1b2&bp2*p2a1&a*p1ap1b2&ap2*p11&b*p2p1b1&bp2*p2a2&a*p16.2使用指针访问数组元素使用指针访问数组元素inta100;数组名代表一个地数组名代表一个地址,它的值是数址,它的值是数组首元素的地址组首元素的地址(基地址)(基地址)a+i是距数组是距数组a的的基
15、地址的第基地址的第i个偏个偏移移3000a0地址地址 内容内容 数组元素数组元素3004a13396a99aiaa+1a+99a+i&ai*(a+i)sum=0;for(i=0;i100;i+)sum=sum+ai;*(a+i)下标运算符下标运算符的含义的含义指针和数组的关系指针和数组的关系任何由数组下标来实现的操作都能用指针任何由数组下标来实现的操作都能用指针来完成来完成double*p,*q;nq-p两两个个相相同同类类型型的的指指针针相相减减,表表示示它它们们之之间间相相隔隔的的存存储储单单元元的的数目数目np+1/p-1指向下一个存储单元指向下一个存储单元/指向上一个存储单元指向上一个
16、存储单元n其他操作都是非法的其他操作都是非法的指针相加、相乘和相除,或指针加上和减去一个浮点数指针相加、相乘和相除,或指针加上和减去一个浮点数npq两个相同类型指针可以用关系运算符比较大小两个相同类型指针可以用关系运算符比较大小指针的算术运算和比较运算指针的算术运算和比较运算pq3000a0地址地址 内容内容 数组元素数组元素3008a1aa+1指针和数组的关系指针和数组的关系inta100,*p;p=a;或或p=&a0;pp+1p+99p+i3000a0地址地址 内容内容 数组元素数组元素3004a13396a99aiaa+1a+99a+i&aiaia+i*(a+i)p+i*(p+i)&pi
17、pip=a;sum=0;for(i=0;i100;i+)sum=sum+pi;用指针完成对数组的操作用指针完成对数组的操作inta100,*p;移动指针移动指针p3000a0地址地址 内容内容 数组元素数组元素3002a13198a99aiaa+1a+99a+isum=0;for(p=a;p=&a99;p+)sum=sum+*p;ppp效率比较效率比较分析:以一维数组为例分析:以一维数组为例typeaM;使用数组名和下标的方式使用数组名和下标的方式访问访问整个数组元素的计算量:整个数组元素的计算量: 1.1.访问元素访问元素ai ai 的计算为的计算为 a + i*sizeof(type);
18、a + i*sizeof(type); 1 1次加法,次加法,1 1次乘法运算次乘法运算2.2.访问整个数组元素访问整个数组元素: :for(i = 0; i M; i+)for(i = 0; i M; i+)ai=1;ai=1;M M次加法,次加法,M M次乘法运算次乘法运算数组名和下标的方式访问数组元素与使用指针数组名和下标的方式访问数组元素与使用指针访问数组元素的效率比较访问数组元素的效率比较? ?a0a1aM-2aM-1asizeof(type)使用指针的方式使用指针的方式访问整访问整个数组元素的计算量:个数组元素的计算量:p=a;p=a;for(i = 0; i M; for(i =
19、 0; i M; i+)i+) *p=1;*p=1;p+;p+; M M次加法运算次加法运算a0a1aM-2aM-1asizeof(type)ppppp分析:以二维数组为例分析:以二维数组为例typeaMN;使用数组名和下标的方式使用数组名和下标的方式访问整个访问整个数组元素的计算量数组元素的计算量: : 1.1.访问元素访问元素aij aij 的计算为的计算为 a + (i*N+j)*sizeof(type); a + (i*N+j)*sizeof(type); 2 2次加法,次加法,2 2次乘法运算次乘法运算2.2.访问整个数组元素访问整个数组元素: :for(i = 0; i M; i+
20、)for(i = 0; i M; i+)for(j = 0; j N; j+)for(j = 0; j N; j+)aij=1;aij=1;2MN2MN次加法,次加法,2MN2MN次乘法运算次乘法运算sizeof(type)a00a01a0N-1aM-1N-1a使用指针的方式使用指针的方式访问整个数访问整个数组元素组元素 : : p=a;p=a;for(i = 0; i M; i+)for(i = 0; i M; i+)for(j = 0; j N; j+)for(j = 0; j N; j+) *p=1;*p=1;p+;p+; MNMN次加法运算次加法运算sizeof(type)a00a01
21、a0N-1aM-1N-1appppppp两种方式的运算比较两种方式的运算比较aMaMN数组名和下标M次加法,M次乘法运算2MN次加法,2MN次乘法运算指针M次加法运算MN次加法运算数组访问方式#includeintmain(void)doublea2,*p,*q;p=&a0;q=p+1;printf(%dn,q-p);printf (p = %pn, p); printf (q = %pn, q); return0;例例6-10使用指针计算数组元素个数和使用指针计算数组元素个数和数组元素的存储单元数数组元素的存储单元数1指针指针p p和和q q之间元素的个数之间元素的个数地址值地址值pq001
22、2FF54a0地址地址 内容内容 数组元素数组元素0012FF5Ca1aa+1%p表示输出这个指针变量的值。表示输出这个指针变量的值。p = 0012FF54q = 0012FF5C#includeintmain(void)inti,a10,*p;longsum=0;printf(Enter10integers:);for(i=0;i10;i+)scanf(%d,&ai);for(p=a;p=a+9;p+)sum=sum+*p;printf(sum=%ldn,sum);return0;例例6-11使用指针计算数组元素之和使用指针计算数组元素之和Enter10integers:109876543
23、21sum=55p3000a0地址地址 内容内容 数组元素数组元素3004a13036a9aiaa+1a+9a+ippp6.3加密问题加密问题字符串字符串:字符数组字符数组:字符指针字符指针:6.3.1程序解析程序解析6.3.2字符数组和字符指针字符数组和字符指针6.3.1程序解析加密程序解析加密#defineMAXLINE100voidencrypt(char*s);intmain(void)charlineMAXLINE;printf(Inputthestring:);gets(line);encrypt(line);printf(“Afterbeingencrypted:%sn,line
24、);return0;voidencrypt(char*s)for(;*s!=0;s+)if(*s=z)*s=a;else*s=*s+1;Inputthestring:hellohangzhouAfterbeingencrypted:ifmmp!ibohaipv加密函数的两种实现加密函数的两种实现voidencrypt(chars)inti;for(i=0;si!=0;i+)if(si=z)si=a;elsesi=si+1;voidencrypt(char*s)for(;*s!=0;s+)if(*s=z)*s=a;else*s=*s+1;解密函数怎样实现解密函数怎样实现?voidencrypt(
25、char*s)for(;*s!=0;s+)if(*s=z)*s=a;else*s=*s+1;voiddecrypt(char*s)?6.3.2字符串和字符指针字符串和字符指针n字符串常量字符串常量arraypoint用一对双引号括起来的字符序列用一对双引号括起来的字符序列被看做一个特殊的一维字符数组被看做一个特殊的一维字符数组,在内存中连续在内存中连续存放存放实质上是一个指向该字符串首字符的指针常量实质上是一个指向该字符串首字符的指针常量charsa=array;char*sp=point;charsa=array;char*sp=point;printf(%s,sa);printf(%s,s
26、p);printf(%sn,string);arraypointstringprintf(%s,sa+2);printf(%s,sp+3);printf(%sn,string+1);raynttring数组名数组名sa、指针、指针sp和字符串和字符串string的值都是的值都是地地址址字符数组与字符指针的重要区别字符数组与字符指针的重要区别charsa=Thisisastring;char*sp=Thisisastring;saT h i si sas t r i n g 0spT h i si sas t r i n g 0如果要改变数组如果要改变数组sa所代表的字符串,只能改变所代表的字符串,只能改变数组元素的内容数组元素的内容如果要改变指针如果要改变指针sp所代表的字符串,通常直接所代表的字符串,通常直接改变指针的值,让它指向新的字符串改变指针的值,让它指向新的字符串练习练习:定义一个数组将下表的星期信息组织起来,输入一定义一个数组将下表的星期信息组织起来,输入一个字符串,在表中查找,若存在,输出该字符串在个字符串,在表中查找,若存在,输出该字符串在表中的序号,否则输出表中的序号,否则输出-1。(用字符数组实现用字符数组实现)SundayMondayTuesdayWednesdayThursdayFridaySaturday