C语言程序设计基础与实训教程 第9章

上传人:E**** 文档编号:89423479 上传时间:2019-05-25 格式:PPT 页数:94 大小:213.50KB
返回 下载 相关 举报
C语言程序设计基础与实训教程 第9章_第1页
第1页 / 共94页
C语言程序设计基础与实训教程 第9章_第2页
第2页 / 共94页
C语言程序设计基础与实训教程 第9章_第3页
第3页 / 共94页
C语言程序设计基础与实训教程 第9章_第4页
第4页 / 共94页
C语言程序设计基础与实训教程 第9章_第5页
第5页 / 共94页
点击查看更多>>
资源描述

《C语言程序设计基础与实训教程 第9章》由会员分享,可在线阅读,更多相关《C语言程序设计基础与实训教程 第9章(94页珍藏版)》请在金锄头文库上搜索。

1、第1页,第9章,指 针,第2页,主要内容,指针和地址的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量 字符串的指针和指向字符串的指针变量 函数的指针和指向函数的指针变量 返回指针值的函数 指针数组和指向指针的指针,第3页,9.1 指针和地址的概念,如果在程序中定义了一个变量,在编译时系统根据程序中定义的变量类型,给这个变量分配一定长度的内存单元。例如,一般微型计算机使用的C系统为整型变量分配2个字节,为实型变量分配4个字节,为字符型变量分配1个字节。内存区的每一个字节有一个编号,这就是“地址”,相当于旅馆的房间号。在地址所标志的内存单元中存放数据,相当于在旅馆的各个房间中

2、居住旅客一样。,第4页,9.1 指针和地址的概念,在程序中一般是通过变量名来对内存单元进行存取操作的。但是实际上,程序经过编译后,将变量名转换成变量的地址,对变量值的存取是通过地址进行的。所以,需要弄清楚内存单元的地址与内存单元的内容这两个概念。,第5页,9.1 指针和地址的概念,20002002200430002000369内存用户数据区变量i变量j变量k变量i_pointer内存单元 假设程序已定义了3个整型变量i、j、k,编译时系统分配2000和2001两个字节给变量i,分配2002和2003两个字节给变量j,分配2004和2005两个字节给变量k。那么,printf(“%d“,i)是这

3、样执行的:根据变量名与地址的对应关系(这个对应关系是在编译时分配存储单元确定的),找到变量i的地址2000,然后从由2000开始的两个字节中取出数据(即变量的值3),把它输出。如果用scanf(“%d“,&i)输入,执行时,就把从键盘输入的值送到地址为2000开始的整型存储单元中。如果有语句“k=i+j”,则从2000、2001字节取出i的值(3),再从2002、2003字节取出j的值(6),将它们相加后再将其和(9)送到k所占用的2004、2005字节单元中去。这种按变量地址存取变量值的方式称为“直接访问”方式。,第6页,9.1 指针和地址的概念,还可以采用另一种称为“间接访问”的方式。将变

4、量i的地址存放在另一个变量中,按C语言的规定,可以在程序中定义整型变量、实型变量、字符变量等,也可以定义这样一种特殊的变量,它是存放地址的。如定义一个变量i_pointer,用来存放整型变量的地址,它被分配为3000、3001字节。可以通过下面语句将i的地址(2000)存放到i_pointer中: i_pointer=,第7页,9.1 指针和地址的概念,这时,i_pointer的值就是2000,即变量i所占用单元的起始地址。要存取变量i的值,也可以采用间接方式:先找到存放“i的地址”的变量,从中取出i的地址(2000),然后到2000、2001字节取出i的值(3)。 打个比方,为了开一个A抽屉

5、,有两种办法:一种是将A钥匙带在身上,需要时直接找出该钥匙打开抽屉,取出所需的东西;另一种是为安全起见,将该A钥匙放到另一抽屉B中锁起来。如果需要打开A抽屉,就需要先找出B钥匙,打开B抽屉,取出A钥匙,再打开A抽屉,取出A抽屉中的东西,这就是“间接访问”。,第8页,9.2 变量的指针和指向变量的指针变量,指针变量的定义 指针变量的引用 指针变量作为函数参数,第9页,9.2.1 指针变量的定义,C语言规定所有变量在使用前必须定义,指定其类型,并按此分配内存单元。指针变量不同于整型变量和其他类型的变量,它是用来专门存放地址的,必须将它定义为指针类型。,第10页,9.2.1 指针变量的定义,例如:

6、int i,j; int *pointer1, *pointer2; 第一行定义整型变量i和j,第二行定义指向整型变量的指针 变量pointer1和pointer2。第二行中左端的int是在定义指针变 量时指定的“基类型”。指针变量的基类型用来指定该指针 变量可以指向的变量的类型。例如,上面定义的指针变量 pointer1和pointer2可以用来指向整型变量i和j,但不能指向 实型变量a和b。 定义指针变量的一般形式为: 基类型 *指针变量名,第11页,9.2.1 指针变量的定义,例如: float *pointer3; /*pointer3是指向实型变量的指针变量*/ char *poin

7、ter4; /*pointer4是指向字符型变量的指针变量*/ 在定义了指针变量后,就可以建立指针变量和变量的“指向” 关系了。例如,有以下变量定义: float a; char c; 则下面的赋值语句就可以建立指针变量和变量的“指向”关 系了: pointer3=,第12页,9.2.1 指针变量的定义,其含义是:将变量a的地址存放到指针变量pointer3 中,将变量c的地址存放到指针变量pointer4中,这 样,pointer3就“指向”了变量a,pointer4就“指向”了 变量c。 但是,在定义指针变量时需要注意: 指针变量前的“*”只是定义指针变量的一个标志,指针变量名不包含“*”

8、。 定义指针变量时必须指定基类型,并且一个指针变量只能指向同一个类型的变量,即整型指针变量只能指向整型变量,而不能指向实型变量。,第13页,9.2.2 指针变量的引用,程序中使用指针变量,不是取用存放在指针变量里的地址,就是取用指针变量所指向变量的值。我们首先来了解关于指针的两种运算符。 地址运算符”,那么*pointer代表变量num的值。,第14页,9.2.2 指针变量的引用,【例】输入两个整数,按大小顺序输出。 main() int *p1,*p2,*p,a,b; p1= 程序运行情况如下: 3,5 a=3,b=5 max=5,min=3,第15页,9.2.3 指针变量作为函数参数,【例

9、】阅读程序,写出程序输出结果。 #include void nextS(int *h,int *m,int *s) if(+*s60) return; *s=0; if(+*m60) return; *m=0; *h=(*h+1)%24; void main() int hour=23,minute=59,second=59; nextS( 程序的输出结果是:0 0 0,第16页,9.3 数组的指针和指向数组的指针变量,指向数组元素的指针 通过指针引用数组元素 数组名作函数参数 指向多维数组的指针和指针变量,第17页,9.3.1 指向数组元素的指针,在前面已经介绍过,定义了一个数组后,数组元素

10、 的引用和变量的引用相似。同理,指向数组元素的 指针使用方法与指向变量的指针使用方法相同。例 如,有以下定义: int a10; /*定义包含10个元素的整型数组a*/ int *p; /*定义指向整型变量的指针变量p*/ 那么 p=,第18页,9.3.2 通过指针引用数组元素,定义了指向数组元素的指针变量后,就可以 通过指针变量引用数组的元素了。假设p已 被定义为指针变量,并且指向某一个数组元 素,那么以下赋值语句: *p=1; 表示把1赋给p当前指向的数组元素。,第19页,9.3.2 通过指针引用数组元素,C语言规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素

11、(不是将p的值简单地进行加1运算),当然,如果p指向的是数组的最后一个元素,则p+1指向的单元就会超出数组存储单元的范围了。例如,数组元素是整型,每个元素占2个字节的存储单元,则p+1的含义是使p的值(地址)加2个字节,指向数组的下一个元素。p+1所代表的地址实际上是p+1d,d是一个数组元素所占的字节数(对于实型,d=4,对于字符型,d=1)。,第20页,9.3.2 通过指针引用数组元素,【例】输出数组中的全部元素。 假设有一个a数组,整型,有10个元素,可以用以下3种方法实现: (1)下标法。 main() int a10; int i; for(i=0;i10;i+) scanf(“%d

12、“, ,第21页,9.3.2 通过指针引用数组元素,通过数组名计算数组元素地址,找出元素的值。 main() int a10; int i; for(i=0;i10;i+) scanf(“%d“, ,第22页,9.3.2 通过指针引用数组元素,用指针变量指向数组元素。 main() int a10; int *p,i; for(i=0;i10;i+) scanf(“%d“, 以上3个程序的运行情况均如下: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0,第23页,9.3.2 通过指针引用数组元素,对3种方法的比较: 第(1)和(2)种方法的执行效率是相同的。C编

13、译系统是将ai转换为*(a+i)处理的,即先计算元素地址。因此用第和种方法找出数组元素费时较多。 第(3)种方法比(1)和(2)两种方法访问数组元素要快,用指针变量直接指向元素,不必每次都重新计算地址,像p+这样的自加操作是比较快的。这种有规律地改变地址值(p+)能大大提高执行效率。 用下标法比较直观,能直接知道是第几个元素。例如,a3是数组中序号为3的元素(第四个元素)。用地址法或指针变量的方法不直观,难以很快判断出当前处理的是哪一个元素,需要仔细分析指针变量p的当前指向,才能判断当前输出的是第几个元素。,第24页,9.3.2 通过指针引用数组元素,虽然使用指针变量访问数组元素效率高,但要注

14、意以下几个问题: 指针变量可以实现使本身的值改变。例如,使用p+使p的值不断改变,这是合法的。但要注意,不能使a的值改变(如使用a+)。以下用法是错误的: for(p=a;a(p+10);a+) printf(“%d “,*a);,第25页,9.3.2 通过指针引用数组元素,因为a是数组名,代表数组的首地址,它的值在程序运行期间是固定不变的,是 常量。而a+的含义是将数组首地址a自增1,这是无法实现的。 程序中操作指针时,要注意指针变量的当前值。例如使用以下程序输出数组的元素: main() int *p,i,a10; p=a; for(i=0;i10;i+) scanf(“%d“,p+);

15、printf(“n“); for(i=0;i10;i+,p+) printf(“%d “,*p); 程序运行的情况如下: 1 2 3 4 5 6 7 8 9 0 -14 285 1 -16 2328 -12 0 14915 16732 17710,第26页,9.3.2 通过指针引用数组元素,从上面的程序可以看到,虽然定义数组时指定它包含10个元素,用p指向数组的第一个元素,但指针变量可以指到数组以后的内存单元。如果有p10,C编译程序并不认为非法,系统把它按*(a+10)处理,即先找出(a+10)的值(是一个地址),然后找出它所指向的单元的内容。,第27页,9.3.2 通过指针引用数组元素,注

16、意指针变量的运算。如果先使p指向数组a(即p=a),则: p+(或p+=1),使p指向下一元素,即a1。若再执行 *p,取出下一个元素a1的值。 *p+,由于+和*同优先级,结合方向为自右而左,因 此它等价于*(p+),作用是先得到p指向的变量的值(即 *p),然后再使p+1p。例如,下面的for语句: for(i=0;i10;i+,p+) printf(“%d “,*p); 可以改写成: for(i=0;i10;i+) printf(“%d “,*p+);,第28页,9.3.2 通过指针引用数组元素, *(p+)与*(+p)作用不同。前者是先取*p的值,后使p加1。后者是先 使p加1,再取*p。若p初值为a(即&a0),输出*(p+)时,得到a0的 值,而输出*(+p),则得到a1的值。 (*p)+表示p所指向的元素加1,即(a0)+,如果a0=3,则(a0)+

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号