《c语言教程第6章.ppt》由会员分享,可在线阅读,更多相关《c语言教程第6章.ppt(29页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第六章第六章 指针指针地址和指针的概念指指针针是是C C中中一一个个重重要要概概念念,也也是是C C的的重重要要特特色色,可可以以有有效效地地表表示示复复杂杂的的数数据据结结构构,能能动动态态分分配配内存,能直接处理内存地址等。内存,能直接处理内存地址等。指指针针的的概概念念比比较较复复杂杂,使使用用很很灵灵活活,不不易易掌掌握握,因此要多做练习。因此要多做练习。6-1 指针概述地址与指针地址与指针地址与取地址运算地址与取地址运算CC语言中变量、数组、函数等都占用一定的内存空间,语言中变量、数组、函数等都占用一定的内存空间,地址是指该内存空间的第一个字节的地址。地址是指该内存空间的第一个字节的
2、地址。CC语言中取地址运算符:语言中取地址运算符:&。指针与指针变量指针与指针变量指针:就是地址,是变量的地址。指针:就是地址,是变量的地址。指针变量:存放变量地址的变量指针变量:存放变量地址的变量 。指针的类型与指针的定义指针的类型与指针的定义指针所指向的对象的类型即是指针的类型。指针所指向的对象的类型即是指针的类型。指针的定义:只要在变量名前加指针的定义:只要在变量名前加“*”“*”即可。即可。例:例:int*p int*p 表示表示p p是一个指向整型变量的指针。是一个指向整型变量的指针。注意:注意:*表示其后的变量是指针,指针变量是表示其后的变量是指针,指针变量是p p而非而非*p*p
3、。指针变量一般占指针变量一般占2 2个字节,用来存放一个地址。个字节,用来存放一个地址。例例L6-0-1 L6-0-1 变量、地址、指针、指针的地址。变量、地址、指针、指针的地址。指针变量的引用指针变量的引用&运算符运算符:取地址运算。取地址运算。*运算符运算符:指针运算(指向运算,或间接运算),指针运算(指向运算,或间接运算),*p*p表表示示p p所指向的变量。所指向的变量。例例L6-1&L6-1&与与*运算符。运算符。i110&i1p1i220&i2p2i110&i1p1i220&i2p2例例L6-2 L6-2 使两个指针变量交换指向。使两个指针变量交换指向。i110&i1p1i220&
4、i2p2i110&i1p1i220&i2p2例例L6-3 L6-3 交换两个指针变量所指向变量的值。交换两个指针变量所指向变量的值。指向指针的指针指向指针的指针 int I,*p1,*p2;int I,*p1,*p2;3i&ip1&p1p2例L6-3-2多重指针:从理论上讲,可以有多重指针,但一多重指针:从理论上讲,可以有多重指针,但一般极易出错,不提倡使用多重指针。般极易出错,不提倡使用多重指针。例例L6-4 L6-4 多重指针。多重指针。习题习题5-9 5-9 统计单词与空格数。统计单词与空格数。习题习题5-14 5-14 字符串转换为大写、小写(数组法)字符串转换为大写、小写(数组法)习
5、题习题5-14-2 5-14-2 字符串转换为大写、小写(指针法)字符串转换为大写、小写(指针法)6-2 指针与数组一维数组的指针表示一维数组的指针表示ai:ai:下标法访问数组元素。下标法访问数组元素。*(a+i):*(a+i):地址法访问数组元素。地址法访问数组元素。(a+ia+i表示:从数组表示:从数组a a的首地的首地址开始的第址开始的第i i个元素。)个元素。)例例L6-5L6-5A0=1A0=1A1=3A1=3A2=5A2=5A3=7A3=7A4=9A4=9aa+1a+2a+3a+4ffd0ffd2ffd4ffd6ffd8注意:对数组对数组a a,不能用自增(减)进行运算,不能用自
6、增(减)进行运算(a+,a-)(a+,a-),因为数组的首地址是一个常数。,因为数组的首地址是一个常数。虽然可用多种方法访问数组元素,效率不同,用虽然可用多种方法访问数组元素,效率不同,用指针访问的速度最快,它不要进行转换。指针访问的速度最快,它不要进行转换。用指针访问数组时用指针访问数组时(主要是赋值主要是赋值),一定要记住不,一定要记住不能越界,否则可能带来严重后果。能越界,否则可能带来严重后果。用指针访问数组时,因为总是从指针当前位置开用指针访问数组时,因为总是从指针当前位置开始,所以要注意指针的当前值。(例始,所以要注意指针的当前值。(例L6-5L6-5的最后的最后一次。)一次。)例例
7、L6-6 L6-6 输入若干个温度,求平均值。(用数组)输入若干个温度,求平均值。(用数组)例例L6-6-2 L6-6-2 输入若干个温度,求平均值。(用指针)输入若干个温度,求平均值。(用指针)强调一维数组的两个结论CC中,一维数组名代表该数组的起始地址。中,一维数组名代表该数组的起始地址。CC中,一维数组的任何一个元素的地址,都可用中,一维数组的任何一个元素的地址,都可用其数组名加上一个偏移量来表示。其数组名加上一个偏移量来表示。这两个结论可以推广至任意维数组都适用。这两个结论可以推广至任意维数组都适用。二维数组的指针表示法二维数组二维数组a a 可以看成是由以下元素构成的一个一可以看成是
8、由以下元素构成的一个一维数组:维数组:a0,a1,a2,ai,a0,a1,a2,ai,所以所以aiai既是一个广义一维数组的元素,也是一既是一个广义一维数组的元素,也是一个一维数组个一维数组aiai的名字的名字(一维数组的首地址一维数组的首地址),所所以以a a是指向是指向aiai起始地址的指针,起始地址的指针,因因aiai是一个一是一个一维数组名,即是一个一维数组的首地址,也就是维数组名,即是一个一维数组的首地址,也就是指针,可见指针,可见a a是一个二级指针。是一个二级指针。二维数组元素及地址的引用:例二维数组元素及地址的引用:例L6-7-0L6-7-0含义含义表示形式表示形式第第0 0行
9、第行第1 1列元素地址列元素地址a0+1,*a+1,*(a+0)+1,&a01a0+1,*a+1,*(a+0)+1,&a01a0+1,*a+1,*(a+0)+1,&a01a0+1,*a+1,*(a+0)+1,&a01第第1 1行第行第2 2列元素地址列元素地址a1+2,*(a+1)+2,&a12a1+2,*(a+1)+2,&a12a1+2,*(a+1)+2,&a12a1+2,*(a+1)+2,&a12第第1 1行第行第2 2列元素的值列元素的值*(a1+2),*(*(a+1)+2),a12*(a1+2),*(*(a+1)+2),a12*(a1+2),*(*(a+1)+2),a12*(a1+2)
10、,*(*(a+1)+2),a12例例L6-7 L6-7 指向数组元素的指针变量。指向数组元素的指针变量。指向一维数组的指针int (*)p5:int (*)p5:表示表示 P P是指向一个一维数组的指针是指向一个一维数组的指针(指向该数组的首地址)。(指向该数组的首地址)。P+P+表示将指针移向表示将指针移向下一个一维数组(指向其首地址)。所以可用它下一个一维数组(指向其首地址)。所以可用它处理二维数组,参见例处理二维数组,参见例L6-8L6-8。指针与字符串字符串是存放在字符数组中的,因此可用指针来字符串是存放在字符数组中的,因此可用指针来访问字符中的字符。访问字符中的字符。例例L6-10
11、L6-10 用三种方式输出字符串:用三种方式输出字符串:1 1、直接输出字符串数组、直接输出字符串数组string:printf(“%s”,string)string:printf(“%s”,string)2 2、直接用指向字符串的指针、直接用指向字符串的指针p:printf(“%s”,p)p:printf(“%s”,p)3 3、用指针逐个字符输出。、用指针逐个字符输出。直接用指针表示字符串:char*p=“C Language”;char*p=“C Language”;表示将字符串表示将字符串“C Language”“C Language”存放在一连续的内存空存放在一连续的内存空间(以间(以
12、00)结束,并将指针)结束,并将指针P P指向该空间的首地址。指向该空间的首地址。上面的程序行也可写成两行:上面的程序行也可写成两行:char*p;char*p;p=“C Language”;p=“C Language”;例例L6-12-1 L6-12-1 指针指向的字符串与数组表示的字符串的区别虽然虽然:char a=“C Language”;char a=“C Language”;char*p=“C Language”;char*p=“C Language”;都可表示字符串,但两者概念并不相同:都可表示字符串,但两者概念并不相同:aa表示是一个表示是一个1111个元素的字符数组,将个元素的
13、字符数组,将C LanguageC Language和和00分别存入分别存入1111个单元。个单元。a a 表示表示首地址,是一个常量,不首地址,是一个常量,不能改变,如能改变,如a+a+是错误的。是错误的。P P只表示一个地址,只表示一个地址,指向指向字符串字符串C LanguageC Language的首地址。的首地址。P P的值的是可以改变的,如:的值的是可以改变的,如:p+p+表示将指针向后移一个单元。表示将指针向后移一个单元。指针数组数组元素都是指针的数组称为指针数组,即指针数组元素都是指针的数组称为指针数组,即指针数组是用来存放一批地址的。主要用来处理字符数组是用来存放一批地址的。
14、主要用来处理字符串数组,如:串数组,如:char*name5=“Li”,“Zhang”,“Ling”,“Sun”,“Wang”char*name5=“Li”,“Zhang”,“Ling”,“Sun”,“Wang”它比用二维数组要节约内存空间(参见它比用二维数组要节约内存空间(参见P195P195、196196的两个图)。的两个图)。例例L6-13L6-13在一批字符串中查找指定字符串。在一批字符串中查找指定字符串。指针数组举例例例L6-15 L6-15 用二级指针表示二维数组,对三个字用二级指针表示二维数组,对三个字符串排升序。符串排升序。例例L6-16 L6-16 用二级指针表示二维数组,输
15、出数组用二级指针表示二维数组,输出数组元素。元素。6-3 指针与函数主要有以下三个方面:主要有以下三个方面:用指针作为函数参数。用指针作为函数参数。函数的返回值是指针。函数的返回值是指针。指向函数的指针。指向函数的指针。指针作为函数参数习题习题5-14-25-14-2已经进行过介绍。已经进行过介绍。指针作为函数的参数时,传递的是地址,如果对指针作为函数的参数时,传递的是地址,如果对地址中的值进行了修改,则修改不是临时的。地址中的值进行了修改,则修改不是临时的。比较以下两个例子:比较以下两个例子:例例L6-18 L6-18 传递的是地址,且对地址中的值进行了改传递的是地址,且对地址中的值进行了改
16、变,所以在主程序中的改变是当然的。变,所以在主程序中的改变是当然的。例例L6-18-2 L6-18-2 传递的是地址,没有对地址中的值进行修传递的是地址,没有对地址中的值进行修改,所以在主程序的不变也是当然的。改,所以在主程序的不变也是当然的。数组指针作为函数的参数用数组与指针作为函数的参数时,实参与形参可用数组与指针作为函数的参数时,实参与形参可以有以下四种组合:以有以下四种组合:实参实参形参形参数组名数组名数组名数组名数组名数组名指针指针指针指针数组名数组名指针指针指针指针例例L6-21 L6-21 求一维数组中下标为奇数的元素之和。求一维数组中下标为奇数的元素之和。指向函数的指针函数包括
17、一系列的指令,在内存中也占据一片存函数包括一系列的指令,在内存中也占据一片存储单元,也有一个地址,通过该地址就可找到该储单元,也有一个地址,通过该地址就可找到该 函数,该地址就是该函数,该地址就是该函数的指针函数的指针(函数的入口地函数的入口地址址)。函数指针的定义:函数指针的定义:类型类型 (*指针名)();指针名)();给函数指针赋值:给函数指针赋值:指针名指针名=函数名;函数名;用函数指针调用函数:用函数指针调用函数:(*(*指针名指针名)()(实参实参)例例L6-26L6-26 用函数指针两次调用不同的函数,分别实现不用函数指针两次调用不同的函数,分别实现不同的功能。同的功能。main
18、()函数中的参数CC语言中的语言中的main()main()函数也可以有参数,一般格式函数也可以有参数,一般格式如下:如下:main(int argc,char*argv)main(int argc,char*argv)表示命令行表示命令行参数的个数参数的个数表示命令行表示命令行参数数组参数数组main()参数举例如:如:CC编译后的文件名为编译后的文件名为 cfilecfile.exe.exe而执行时用:而执行时用:cfilecfile computer language computer language 则:则:argcargc=3=3argvargv=“=“cfilecfile”,“c
19、omputer”,”,“computer”,“language”;“language”;例例L6-30 L6-30 输出用户输入的参数。输出用户输入的参数。常用指针类型变量归纳定义形式定义形式含义含义int*p;int*p;P P为指向整型数据的指针变量为指向整型数据的指针变量int(*p)n;int(*p)n;P P为指向含为指向含n n个元素的一维数组的指针变量个元素的一维数组的指针变量int(*p)();int(*p)();P P为指向函数的指针,该函数带回一个整型值为指向函数的指针,该函数带回一个整型值int*pn;int*pn;P P为含为含n n个元素的指针数组,每个元素指向一个元
20、素的指针数组,每个元素指向一个整型数据。个整型数据。int*p();int*p();P P为指针函数,该函数带回一个指向整型值的为指针函数,该函数带回一个指向整型值的指针。指针。int*p;int*p;P P为指向指针的指针,被指向的指针变量是一为指向指针的指针,被指向的指针变量是一个指向整型值的指针。个指向整型值的指针。int int(*p)n;(*p)n;P P为指向指针的指针,被指向的指针变量又指为指向指针的指针,被指向的指针变量又指向一个一维数组。向一个一维数组。P+P+(或(或p+=1p+=1):):使使p p指向下一元素。指向下一元素。*p+p+:因因+与与*同同优优先先级级,结结
21、合合方方向向为为自自右右向向左左,所所以以等等价价于于*(*(p+p+),先先用用后后加加,即即先先得得到到变变量量的的值值(*(*p)p),再再使使p p加加1 1。*(*(p+)p+)与与*(+*(+p)p)不不同同:前前者者是是先先取取*p p值值,后后使使p p加加1 1;后后者是者是p p先加先加1 1,再取,再取*p p值值(下一单元的值。下一单元的值。)(*(*p)+p)+:表示表示p p所指向的元素值加所指向的元素值加1 1,而不是指针加,而不是指针加1 1。如果如果P P当前指向数组当前指向数组a a的第的第 i i 个元素,则:个元素,则:*(*(p-)p-)相相当当于于 ai-ai-,先先对对p p进进行行*运运算算,再再使使p p自自减。减。*(+*(+p)p)相当于相当于 a+ia+i,先使先使p p自加,再作自加,再作*运算。运算。*(-*(-p)p)相当于相当于 a-ia-i,先使先使p p自减,再作自减,再作*运算。运算。指针变量的运算小结
限制150内