中国高等院校计算机基础教育课程体系规划教材讲授第6章

上传人:鲁** 文档编号:571974757 上传时间:2024-08-12 格式:PPT 页数:58 大小:1,000.50KB
返回 下载 相关 举报
中国高等院校计算机基础教育课程体系规划教材讲授第6章_第1页
第1页 / 共58页
中国高等院校计算机基础教育课程体系规划教材讲授第6章_第2页
第2页 / 共58页
中国高等院校计算机基础教育课程体系规划教材讲授第6章_第3页
第3页 / 共58页
中国高等院校计算机基础教育课程体系规划教材讲授第6章_第4页
第4页 / 共58页
中国高等院校计算机基础教育课程体系规划教材讲授第6章_第5页
第5页 / 共58页
点击查看更多>>
资源描述

《中国高等院校计算机基础教育课程体系规划教材讲授第6章》由会员分享,可在线阅读,更多相关《中国高等院校计算机基础教育课程体系规划教材讲授第6章(58页珍藏版)》请在金锄头文库上搜索。

1、中国高等院校计算机中国高等院校计算机基础教育课程体系规基础教育课程体系规划教材讲授划教材讲授-第第6章章为了说清楚什么是指针,必须弄清楚数据在内存中是为了说清楚什么是指针,必须弄清楚数据在内存中是如何存储的,又是如何读取的。如何存储的,又是如何读取的。如果在程序中定义了一个变量,在编译时就给这个变如果在程序中定义了一个变量,在编译时就给这个变量分配内存单元。量分配内存单元。系统根据程序中定义的变量类型,系统根据程序中定义的变量类型,分配一定长度的空间分配一定长度的空间。例如,。例如,C+编译系统一般为整编译系统一般为整型变量分配型变量分配4个字节,为单精度浮点型变量分配个字节,为单精度浮点型变

2、量分配4个字个字节,为字符型变量分配节,为字符型变量分配1个字节。内存区的每一个字个字节。内存区的每一个字节有一个编号,节有一个编号, 6.1 指针的概念指针的概念请务必弄清楚一个内存单元的地址与内存单元的内容请务必弄清楚一个内存单元的地址与内存单元的内容这两个概念的区别。这两个概念的区别。在程序中一般是通过变量名来对在程序中一般是通过变量名来对内存单元进行存取操作的。其实程序经过编译以后已内存单元进行存取操作的。其实程序经过编译以后已经将变量名转换为变量的地址,对变量值的存取都是经将变量名转换为变量的地址,对变量值的存取都是通过地址进行的。通过地址进行的。这种按变量地址存取变量值的方式这种按

3、变量地址存取变量值的方式称为称为直接存取方式直接存取方式,或,或直接访问方式直接访问方式。还可以采用另一种称为还可以采用另一种称为间接存取间接存取(间接访问间接访问)的方式。的方式。可以在程序中定义这样一种特殊的变量,它是专门用可以在程序中定义这样一种特殊的变量,它是专门用来存放地址的。来存放地址的。 指针变量是一种特殊的变量,它和以前学过的其他类指针变量是一种特殊的变量,它和以前学过的其他类型的变量的不同之处是:型的变量的不同之处是: 用它来指向另一个变量。用它来指向另一个变量。为了表示指针变量和它所指向的变量之间的联系,为了表示指针变量和它所指向的变量之间的联系,在在C+中用中用“*”符号

4、表示指向符号表示指向,例如,例如,i_pointer是一是一个指针变量,而个指针变量,而*i_pointer表示表示i_pointer所指向的变所指向的变量,见图量,见图6.3。下面两个语句作用相同:下面两个语句作用相同: i=3; *i_pointer=3; 图图6.36.2 变量与指针变量与指针C+规定所有变量在使用前必须先定义,即指定其类规定所有变量在使用前必须先定义,即指定其类型。在编译时按变量类型分配存储空间。型。在编译时按变量类型分配存储空间。对指针变量对指针变量必须将它定义为指针类型。必须将它定义为指针类型。先看一个具体例子:先看一个具体例子: int i,j; /定义整型变量定

5、义整型变量i,jint *pointer_1, *pointer_2; /定义指针变量定义指针变量*pointer_1,*pointer_2第第2行开头的行开头的int是指:是指: 所定义的指针变量是指向整型所定义的指针变量是指向整型数据的指针变量。数据的指针变量。也就是说,指针变量也就是说,指针变量pointer_1和和pointer_2只能用来指向整型数据只能用来指向整型数据(例如例如i和和j),这个这个int就是指针变量的基类型。就是指针变量的基类型。指针变量的基类型用来指定指针变量的基类型用来指定该指针变量可以指向的变量的类型该指针变量可以指向的变量的类型。6.2. 定义指针变量定义指

6、针变量定义指针变量的一般形式为定义指针变量的一般形式为基类型基类型 *指针变量名;指针变量名;下面都是合法的定义:下面都是合法的定义: float *pointer_3; / pointer_3是指向单精度型数据的指针变量是指向单精度型数据的指针变量char *pointer_4; / pointer_4是指向字符型数据的指针变量是指向字符型数据的指针变量请注意:请注意: 指针变量名是指针变量名是pointer_3和和pointer_4,而不而不是是*pointer_3和和*pointer_4,即即“*”不是指针变量不是指针变量名的一部分,名的一部分,在定义变量时在变量名前加一个在定义变量时在

7、变量名前加一个“*”表示该变量是指针变量表示该变量是指针变量。那么,怎样使一个指针变量指向另一个变量呢?只需那么,怎样使一个指针变量指向另一个变量呢?只需要要把被指向的变量的地址赋给指针变量把被指向的变量的地址赋给指针变量即可。例如:即可。例如: pointer_1=&i; /将变量将变量i的地址存放到指针变量的地址存放到指针变量pointer_1中中pointer_2=&j; /将变量将变量j的地址存放到指针变量的地址存放到指针变量pointer_2中中这样,这样,pointer_1就指向了变量就指向了变量i,pointer_2就指向了就指向了变量变量j。见图见图6.4。图图6.4一般的一般

8、的C+编译系统为每一个指针变量分配编译系统为每一个指针变量分配4个字节个字节的的存储单元存储单元,用来存放变量的地址。,用来存放变量的地址。在定义指针变量时要注意:在定义指针变量时要注意: (1) 不能用一个整数给一个指针变量赋初值。不能用一个整数给一个指针变量赋初值。(2) 在定义指针变量时必须指定基类型。在定义指针变量时必须指定基类型。有两个与指针变量有关的运算符:有两个与指针变量有关的运算符: (1) 取地址运算符。取地址运算符。(2) *指针运算符(或称间接访问运算符)。指针运算符(或称间接访问运算符)。例如:例如: &a为变量为变量a的地址,的地址,*p为指针变量为指针变量p所指向的

9、所指向的存储单元。存储单元。6.2.2 引用指针变量引用指针变量例例6.1 通过指针变量访问整型变量。通过指针变量访问整型变量。#include using namespace std;int main( )int a,b; /定义整型变量定义整型变量a,bint *pointer_1,*pointer_2; /定义指针变量定义指针变量a=100;b=10; /对对a,b赋值赋值pointer_1=&a; /把变量的地址赋给把变量的地址赋给pointer_1pointer_2=&b; /把变量的地址赋给把变量的地址赋给pointer_2couta bendl; /输出输出a和和b的值的值cou

10、t*pointer_1 *pointer_2endl; /输出输出*pointer_1和和*pointer_2的值的值return 0;运行结果为运行结果为100 10 (a和和b的值的值)100 10 (*pointer_1和和*pointer_2的值的值)例例6.2 输入输入a和和b两个整数,按先大后小的顺序输出两个整数,按先大后小的顺序输出a和和b(用指针变量处理用指针变量处理)。解此题的思路是:解此题的思路是: 设两个指针变量设两个指针变量p1和和p2,使它们使它们分别指向分别指向a和和b。使使p1指向指向a和和b中的大者,中的大者,p2指向小指向小者,顺序输出者,顺序输出*p1,*p

11、2就实现了按先大后小的顺序输就实现了按先大后小的顺序输出出a和和b。按此思路编写程序如下:按此思路编写程序如下: #include using namespace std;int main( )int *p1,*p2,*p,a,b;cinab; /输入两个整数输入两个整数p1=&a; /使使p1指向指向ap2=&b; /使使p2指向指向bif(ab) /如果如果ab就使就使p1与与p2的值交换的值交换p=p1;p1=p2;p2=p; /将将p1的指向与的指向与p2的指向交换的指向交换couta=a b=bendl;coutmax=*p1 min=*p2endl;return 0;运行情况如下:

12、运行情况如下: 4578 a=45 b=78max=78 min=45函数的参数不仅可以是整型、浮点型、字符型等数据,函数的参数不仅可以是整型、浮点型、字符型等数据,还可以是指针类型。它的作用是还可以是指针类型。它的作用是将一个变量的地址传将一个变量的地址传送给被调用函数的形参送给被调用函数的形参。例例6.3 题目同例题目同例6.2,即对输入的两个整数按大小顺序,即对输入的两个整数按大小顺序输出。输出。这里用函数处理,而且这里用函数处理,而且用指针类型的数据作函数参数用指针类型的数据作函数参数。程序如下:程序如下: 6.2.3 指针作为函数参数指针作为函数参数#include using na

13、mespace std;int main( ) void swap(int *p1,int *p2); /函数声明函数声明int *pointer_1,*pointer_2,a,b; /定义指针变量定义指针变量pointer_1,pointer_2,整型变量整型变量a,bcinab;pointer_1=&a; /使使pointer_1指向指向apointer_2=&b; /使使pointer_2指向指向bif(ab) swap(pointer_1,pointer_2); /如果如果ab,使使*pointer_1和和*pointer_2互互换换coutmax=a min=bendl;/a已是大数

14、,已是大数,b是小数是小数 return 0;void swap(int *p1,int *p2) /函数的作用是将函数的作用是将*p1的值与的值与*p2的值交换的值交换 int temp;temp=*p1; *p1=*p2;*p2=temp; 运行情况如下:运行情况如下: 45 78 max=78 min=45请注意:请注意: 不要将不要将main函数中的函数中的swap函数调用写成函数调用写成if(ab) swap(*pointer_1,*pointer_2);图图6.9void swap(int x,int y)int temp;temp=x;x=y;y=temp;在在main函数中用函

15、数中用“swap(a,b);”调用调用swap函数,会函数,会有什么结果呢?在函数调用时,有什么结果呢?在函数调用时,a的值传送给的值传送给x,b的的值传送给值传送给y,如图如图6.10(a)所示。执行完所示。执行完swap函数最后函数最后一个语句后,一个语句后,x和和y的值是互换了,但的值是互换了,但main函数中的函数中的a和和b并未互换,如图并未互换,如图6.10(b)所示。也就是说由于虚实所示。也就是说由于虚实结合是采取单向的结合是采取单向的“值传递值传递”方式,只能从实参向形方式,只能从实参向形参传数据,形参值的改变无法回传给实参。参传数据,形参值的改变无法回传给实参。图图6.10为

16、了使在函数中改变了的变量值能被为了使在函数中改变了的变量值能被main函数所用,函数所用,不能采取把要改变值的变量作为参数的办法,而应该不能采取把要改变值的变量作为参数的办法,而应该用指针变量作为函数参数。用指针变量作为函数参数。在函数执行过程中使指针在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来,这样就实现了些变量值的变化依然保留下来,这样就实现了“通过通过调用函数使变量的值发生变化,在主调函数中使用这调用函数使变量的值发生变化,在主调函数中使用这些改变了的值些改变了的值”的目的。的目的。如果想通过

17、函数调用得到如果想通过函数调用得到n个要改变的值,可以采取个要改变的值,可以采取下面的步骤:下面的步骤: 在主调函数中设在主调函数中设n个变量,用个变量,用n个指个指针变量指向它们;针变量指向它们;编写被调用函数,其形参为编写被调用函数,其形参为n个个指针变量,这些形参指针变量应当与主调函数中的指针变量,这些形参指针变量应当与主调函数中的n个指针变量具有相同的基类型;个指针变量具有相同的基类型;在主调函数中将在主调函数中将n个指针变量作实参,将它们的值个指针变量作实参,将它们的值(是地址值是地址值)传给所调传给所调用函数的用函数的n个形参指针变量,这样,形参指针变量也个形参指针变量,这样,形参

18、指针变量也指向这指向这n个变量;个变量;通过形参指针变量的指向,改变通过形参指针变量的指向,改变该该n个变量的值;个变量的值;在主调函数中就可以使用这些改在主调函数中就可以使用这些改变了值的变量。变了值的变量。一个变量有地址,一个数组包含若干元素,每个数组一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元指针变量既然可以指向变量,当然也可以指向数组元素素(把某一元素的地址放到一个指针变量中)。所谓(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针数组

19、元素的指针就是就是数组元素的地址数组元素的地址。int a10; /定义一个整型数组定义一个整型数组a,它有它有10个元素个元素int *p; /定义一个基类型为整型的指针变量定义一个基类型为整型的指针变量pp=&a0; /将元素将元素a0的地址赋给指针变量的地址赋给指针变量p,使使p指向指向a0在在C+中,数组名代表数组中第一个元素中,数组名代表数组中第一个元素(即序号为即序号为0的元素的元素)的地址。的地址。6.3 数组与指针数组与指针 6.3.1 指向数组元素的指针指向数组元素的指针因此,因此,下面两个语句等价下面两个语句等价:p=&a0;p=a;在在定义指针变量时可以给它赋初值定义指针

20、变量时可以给它赋初值: int *p=&a0; /p的初值为的初值为a0的地址的地址也可以写成也可以写成int *p=a; /作用与前一行相同作用与前一行相同可以通过指针引用数组元素。假设可以通过指针引用数组元素。假设p已定义为一个基已定义为一个基类型为整型的指针变量,并已将一个整型数组元素的类型为整型的指针变量,并已将一个整型数组元素的地址赋给了它,使它指向某一个数组元素。如果有以地址赋给了它,使它指向某一个数组元素。如果有以下赋值语句:下赋值语句: *p=1; /对对p当前所指向的数组元素赋予数值当前所指向的数组元素赋予数值1如果指针变量如果指针变量p已指向数组中的一个元素,则已指向数组中

21、的一个元素,则p+1指指向同一数组中的下一个元素。向同一数组中的下一个元素。如果如果p的初值为的初值为&a0,则:则: (1) p+i和和a+i就是就是ai的地址,或者说,它们指向的地址,或者说,它们指向a数数组的第组的第i个元素,个元素,见图见图6.12。图图6.12(2) *(p+i)或或*(a+i)是是p+i或或a+i所指向的数组元素,所指向的数组元素,即即ai。可以看出,可以看出,实际上是变址运算符。对实际上是变址运算符。对ai的求解过的求解过程是:程是: 先按先按a+id计算数组元素的地址,然后找出此计算数组元素的地址,然后找出此地址所指向的单元中的值。地址所指向的单元中的值。(3)

22、 指向数组元素的指针变量也可以带下标,如指向数组元素的指针变量也可以带下标,如pi与与*(p+i)等价。等价。根据以上叙述,根据以上叙述,引用一个数组元素,可用以下方法:引用一个数组元素,可用以下方法: (1) 下标法,如下标法,如ai形式;形式;(2) 指针法,如指针法,如*(a+i)或或*(p+i)。其中其中a是数组名是数组名,p是指向数组元素的指针变量。如果已使是指向数组元素的指针变量。如果已使p的值为的值为a,则则*(p+i)就是就是ai。可以通过指向数组元素的指针找到可以通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高。所需的元素。使用指针法能使目标程序质量高。例例

23、6.5 输出数组中的全部元素。输出数组中的全部元素。假设有一个整型数组假设有一个整型数组a,有有10个元素。要输出各元素个元素。要输出各元素的值有的值有3种方法:种方法: (1) 下标法下标法#include using namespace std;int main( ) int a10;int i;for(i=0;iai; /引用数组元素引用数组元素aicoutendl;for(i=0;i10;i+)coutai ; /引用数组元素引用数组元素aicoutendl;return 0;运行情况如下:运行情况如下: 9 8 7 6 5 4 3 2 1 0 (输入输入10个元素的值个元素的值)9

24、8 7 6 5 4 3 2 1 0 (输出输出10个元素的值个元素的值)(2) 指针法指针法 将上面程序第将上面程序第7行和第行和第10行的行的“ai”改为改为“*(a+i)”,运行情况与运行情况与(1)相同。相同。(3) 用指针变量指向数组元素用指针变量指向数组元素#include using namespace std;int main( ) int a10;int i,*p=a; /指针变量指针变量p指向数组指向数组a的首元素的首元素a0for(i=0;i*(p+i); /输入输入a0a9共共10个元素个元素coutendl;for(p=a;p(a+10);p+)cout*p ; /p先

25、后指向先后指向a0a9 coutendl;return 0;运行情况与前相同。请仔细分析运行情况与前相同。请仔细分析p值的变化和值的变化和*p的值。的值。对对3种方法的比较:种方法的比较: 方法方法(1)和和(2)的执行效率是相同的。第的执行效率是相同的。第(3)种方法比种方法比方法方法(1)、(2)快。这种方法能提高执行效率。快。这种方法能提高执行效率。用下标法比较直观,能直接知道是第几个元素。用地用下标法比较直观,能直接知道是第几个元素。用地址法或指针变量的方法都不太直观,难以很快地判断址法或指针变量的方法都不太直观,难以很快地判断出当前处理的是哪一个元素。出当前处理的是哪一个元素。在用指

26、针变量指向数组元素时要注意:在用指针变量指向数组元素时要注意: 指针变量指针变量p可可以指向有效的数组元素,实际上也可以指向数组以后以指向有效的数组元素,实际上也可以指向数组以后的内存单元。的内存单元。如果有如果有 int a10,*p=a; /指针变量指针变量p的初值为的初值为&a0cout*(p+10); /要输出要输出a10的值的值在使用指针变量指向数组元素时,应切实保证指向数在使用指针变量指向数组元素时,应切实保证指向数组中有效的元素。组中有效的元素。在前面章节中介绍过可以用数组名作函数的参数。前在前面章节中介绍过可以用数组名作函数的参数。前面已经多次强调:面已经多次强调: 数组名代表

27、数组首元素的地址。数组名代表数组首元素的地址。用数组名作函数的参数,传递的是数组首元素的地址。用数组名作函数的参数,传递的是数组首元素的地址。很容易推想:很容易推想: 用指针变量作函数形参,同样可以接用指针变量作函数形参,同样可以接收从实参传递来的数组首元素的地址收从实参传递来的数组首元素的地址(此时,实参是此时,实参是数组名数组名)。6.3.2 用指针变量作函数参数接收数组地址用指针变量作函数参数接收数组地址实际上在函数调用时并不存在一个占有存储空间的形实际上在函数调用时并不存在一个占有存储空间的形参数组,只有指针变量。参数组,只有指针变量。实参与形参的结合,有以下实参与形参的结合,有以下4

28、种形式:种形式: 实实 参参 形形 参参数组名数组名 数组名数组名 数组名数组名 指针变量指针变量 指针变量指针变量 数组名数组名指针变量指针变量 指针变量指针变量在此基础上,还要说明一个问题:在此基础上,还要说明一个问题: 实参数组名实参数组名a代表代表一个固定的地址,或者说是指针型常量,因此要改变一个固定的地址,或者说是指针型常量,因此要改变a的值是不可能的。的值是不可能的。如如 a+; /语法错误,语法错误,a是常量,不能改变是常量,不能改变而形参数组名是指针变量,并不是一个固定的地址值。而形参数组名是指针变量,并不是一个固定的地址值。它的值是可以改变的。在函数调用开始时,它接收了它的值

29、是可以改变的。在函数调用开始时,它接收了实参数组首元素的地址,但在函数执行期间,它可以实参数组首元素的地址,但在函数执行期间,它可以再被赋值。如再被赋值。如 f(array,int n) coutarray; /输出输出array0的值的值array=array+3; /指针变量指针变量array的值改变了,指向的值改变了,指向array3cout*arrendl; /输出输出array3的值的值在在C+中可以用中可以用3种方法访问一个字符串种方法访问一个字符串(前面介绍一种前面介绍一种是用是用字符数组字符数组的方法,一般称为的方法,一般称为Cstring方法;方法;)。1. 用字符数组存放一

30、个字符串用字符数组存放一个字符串例例6.10 定义一个字符数组并初始化,然后输出其中的定义一个字符数组并初始化,然后输出其中的字符串。字符串。#include using namespace std;int main( ) char str=I love CHINA!;coutstrendl;return 0;6.4 字符串与指针字符串与指针运行时输出:运行时输出: I love CHINA!2. 用字符串变量存放字符串用字符串变量存放字符串例例6.11 定义一个字符串变量并初始化,然后输出其中定义一个字符串变量并初始化,然后输出其中的字符串。的字符串。#include #include us

31、ing namespace std;int main( ) string str=I love CHINA!;coutstrendl;return 0;3. 用字符指针指向一个字符串用字符指针指向一个字符串例例6.12 定义一个字符指针变量并初始化,然后输出它定义一个字符指针变量并初始化,然后输出它指向的字符串。指向的字符串。#include using namespace std;int main( ) char *str=I love CHINA!;coutstrendl;return 0;对字符串中字符的存取,可以用下标方法,也可以用对字符串中字符的存取,可以用下标方法,也可以用指针方法

32、。指针方法。例例6.13 将字符串将字符串str1复制为字符串复制为字符串str2。定义两个字符数组定义两个字符数组str1和和str2,再设两个指针变量再设两个指针变量p1和和p2,分别指向两个字符数组中的有关字符,通过改分别指向两个字符数组中的有关字符,通过改变指针变量的值使它们指向字符串中的不同的字符,变指针变量的值使它们指向字符串中的不同的字符,以实现字符的复制。以实现字符的复制。#include using namespace std;int main( ) char str1=I love CHINA!,str220,*p1,*p2;p1=str1;p2=str2;for(;*p1

33、!=0;p1+,p2+) *p2=*p1;*p2=0;p1=str1;p2=str2;coutstr1 is: p1endl;coutstr2 is: p2endl;return 0;运行结果为运行结果为str1 is: I love CHINA!str2 is: I love CHINA!图图6.19这个例子用来说明怎样使用字符指针。其实,对例这个例子用来说明怎样使用字符指针。其实,对例6.13来说,用来说,用string变量来处理是十分简单的:变量来处理是十分简单的: string str1=I love CHINA!,str2; /定义定义string变量变量str2=str1; /将将

34、str1复制到复制到str2指针变量也可以指向一个函数。指针变量也可以指向一个函数。一个函数在编译时被一个函数在编译时被分配给一个入口地址。这个函数入口地址就称为函数分配给一个入口地址。这个函数入口地址就称为函数的指针。的指针。可以用一个指针变量指向函数,然后通过该可以用一个指针变量指向函数,然后通过该指针变量调用此函数。指针变量调用此函数。例例6.14 求和中的大者。求和中的大者。先按一般方法写程序先按一般方法写程序:#include using namespace std;int main( )int max(int x,int y); /函数声明函数声明6.5 函数与指针函数与指针 6.

35、5.1 用函数指针变量调用函数用函数指针变量调用函数int a,b,m;cinab;m=max(a,b); /调用函数调用函数max,求出最大值,赋给求出最大值,赋给mcoutmax=my) z=x;else z=y;return(z);可以用一个指针变量指向可以用一个指针变量指向max函数,然后通过该指针函数,然后通过该指针变量调用此函数。变量调用此函数。定义指向定义指向max函数的指针变量的方函数的指针变量的方法是:法是: int (*p) (int,int); p所指向的函数的形参类型所指向的函数的形参类型 p是指向函数的指针变量是指向函数的指针变量 指针变量指针变量p指向的函数的类型指

36、向的函数的类型请将它和函数请将它和函数max的原型作比较的原型作比较int max(int,int); /max函数原型函数原型可以看出:可以看出: 只是用只是用(*p)取代了取代了max,其他都一样其他都一样。现在将上面程序的主函数修改如下:现在将上面程序的主函数修改如下:#include using namespace std;int main( )int max(int x,int y); /函数声明函数声明int (*p)(int,int); /定义指向函数的指针变量定义指向函数的指针变量pint a,b,m;p=max; /使使p指向函数指向函数maxcinab;m=p(a,b);c

37、outmax=mendl;return 0;请注意第请注意第7行的赋值语句行的赋值语句“p=max;”。此语句千万不此语句千万不要漏写,它的作用是将函数要漏写,它的作用是将函数max的入口地址赋给指针的入口地址赋给指针变量变量p。这时,这时,p才指向函数才指向函数max。见图见图6.20。图图6.20指向函数的指针变量的一般定义形式为指向函数的指针变量的一般定义形式为函数类型函数类型 (*指针变量名)(函数形参表);指针变量名)(函数形参表);在在C语言中,语言中,函数指针变量常见的用途之一是作为函函数指针变量常见的用途之一是作为函数的参数,将函数名传给其他函数的形参数的参数,将函数名传给其他

38、函数的形参。这样就可。这样就可以在调用一个函数的过程中以在调用一个函数的过程中根据给定的不同实参调用根据给定的不同实参调用不同的函数。不同的函数。在面向对象的在面向对象的C+程序设计中,这种用法就比较少了。程序设计中,这种用法就比较少了。6.5.2 用指向函数的指针作函数参数用指向函数的指针作函数参数一个函数可以带回一个整型值、字符值、实型值等,一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。其概念与以前类也可以带回指针型的数据,即地址。其概念与以前类似,只是带回的值的类型是指针类型而已。返回指针似,只是带回的值的类型是指针类型而已。返回指针值的函数简称为指针函数

39、。值的函数简称为指针函数。定义指针函数的一般形式为定义指针函数的一般形式为类型名类型名 *函数名(参数表列)函数名(参数表列);例如例如int *a(int x,int y);6.6 返回指针值的函数返回指针值的函数如果一个数组,其元素均为指针类型数据,该数组称如果一个数组,其元素均为指针类型数据,该数组称为指针数组,一维指针数组的定义形式为为指针数组,一维指针数组的定义形式为类型名类型名*数组名数组长度;数组名数组长度;例如例如int *p4;6.7.2 指向指针的指针指向指针的指针处理指针数组时,设置指针变量,处理指针数组时,设置指针变量,指向指针数组指向指针数组的元素。的元素。6.7 指

40、针数组和指向指针的指针指针数组和指向指针的指针 6.7.1 指针数组的概念指针数组的概念表表6.1 有关指针的数据类型有关指针的数据类型6.8 有关指针的数据类型和指针运算的小结有关指针的数据类型和指针运算的小结 6.8.1 有关指针的数据类型的小结有关指针的数据类型的小结定义定义含义含义int i;定义整型变量定义整型变量int *p;p为指向整型数据的指针变量为指向整型数据的指针变量int an;定义整型数组定义整型数组a,它有它有n个元素个元素int *pn;定义指针数组定义指针数组p,它由它由n个指向整型数据的指针元素组成个指向整型数据的指针元素组成int (*p)n;p为指向含为指向

41、含n个元素的一维数组的指针变量个元素的一维数组的指针变量int f( );f为带回整型函数值的函数为带回整型函数值的函数int *p( );p为带回一个指针的函数,该指针指向整型数据为带回一个指针的函数,该指针指向整型数据int (*p)( );p为指向函数的指针,该函数返回一个整型值为指向函数的指针,该函数返回一个整型值int *p;p是是一一个个指指向向指指针针的的指指针针变变量量,它它指指向向一一个个指指向向整整型型数数据据的的指指针针变量变量对一个数据可以使用对一个数据可以使用“引用引用”(reference),这是这是C+对对C的一个重要扩充,引用是一种新的变量类型,的一个重要扩充,

42、引用是一种新的变量类型,它的作用是为一个变量起一个别名。它的作用是为一个变量起一个别名。假如有一个变量假如有一个变量a,想给它起一个别名想给它起一个别名b,可以这样写:可以这样写: int a; /定义定义a是整型变量是整型变量int &b=a; /声明声明b是是a的引用的引用以上语句声明了以上语句声明了b是是a的引用,即的引用,即b是是a的别名。经过的别名。经过这样的声明后,这样的声明后,a或或b的作用相同,都代表同一变量。的作用相同,都代表同一变量。*6.9 引用引用 6.9.1 什么是变量的引用什么是变量的引用注意:注意: 在上述声明中,在上述声明中,&是引用声明符,并不代表地是引用声明

43、符,并不代表地址。址。不要理解为不要理解为“把把a的值赋给的值赋给b的地址的地址”。声明变量。声明变量b为引用类型,并不需要另外开辟内存单元来存放为引用类型,并不需要另外开辟内存单元来存放b的值。的值。b和和a占内存中的同一个存储单元,它们具有同占内存中的同一个存储单元,它们具有同一地址。一地址。声明声明b是是a的引用,可以理解为:的引用,可以理解为: 使变量使变量b具具有变量有变量a的地址。见图的地址。见图6.26,如果,如果a的值是的值是20,则,则b的的值也是值也是20。图图6.26在声明一个引用类型变量时,必须同时使之初始化,在声明一个引用类型变量时,必须同时使之初始化,即声明它代表哪

44、一个变量。即声明它代表哪一个变量。在声明变量在声明变量b是变量是变量a的引的引用后,在它们所在函数执行期间,该引用类型变量用后,在它们所在函数执行期间,该引用类型变量b始终与其代表的变量始终与其代表的变量a相联系,相联系,不能再作为其他变量不能再作为其他变量的引用的引用(别名别名)。下面的用法不对:下面的用法不对: int a1,a2;int &b=a1;int &b=a2; /企图使企图使b又变成又变成a2的引用(别名)是不行的的引用(别名)是不行的例例6.17 引用和变量的关系。引用和变量的关系。#include #include using namespace std;int main(

45、 ) int a=10;int &b=a; /声明声明b是是a的引用的引用a=a*a; /a的值变化了,的值变化了,b的值也应一起变化的值也应一起变化coutasetw(6)bendl; b=b/5; /b的值变化了,的值变化了,a的值也应一起变化的值也应一起变化coutbsetw(6)aendl;return 0;6.9.2 引用的简单使用引用的简单使用a的值开始为的值开始为10,b是是a的引用,它的值当然也应该是的引用,它的值当然也应该是10,当,当a的值变为的值变为100(a*a的值)时,的值)时,b的值也随之变的值也随之变为为100。在输出。在输出a和和b的值后,的值后,b的值变为的值

46、变为20,显然,显然a的的值也应为值也应为20。运行记录如下:运行记录如下: 100100 (a和和b的值都是的值都是100)2020 (a和和b的值都是的值都是20)有了变量名,为什么还需要一个别名呢?有了变量名,为什么还需要一个别名呢?C+之所以之所以增加引用类型,增加引用类型, 主要是把它作为函数参数,以扩充主要是把它作为函数参数,以扩充函数传递数据的功能。函数传递数据的功能。 到目前为止,本书介绍过函数参数传递的两种情况。到目前为止,本书介绍过函数参数传递的两种情况。(1) 将变量名作为实参和形参。将变量名作为实参和形参。这时传给形参的是变这时传给形参的是变量的值,传递是单向的。如果在

47、执行函数期间形参的量的值,传递是单向的。如果在执行函数期间形参的值发生变化,并不传回给实参。因为在调用函数时,值发生变化,并不传回给实参。因为在调用函数时,形参和实参不是同一个存储单元。形参和实参不是同一个存储单元。例例6.18 要求将变量要求将变量i和和j的值互换。下面的程序无法实的值互换。下面的程序无法实现此要求。现此要求。6.9.3 引用作为函数参数引用作为函数参数#include using namespace std;int main( ) void swap(int,int); /函数声明函数声明int i=3,j=5;swap(i,j); /调用函数调用函数swapcouti j

48、endl; /i和和j的值未互换的值未互换return 0;void swap(int a,int b) /企图通过形参企图通过形参a和和b的值互换,实现实参的值互换,实现实参i和和j的值的值互换互换 int temp;temp=a; /以下以下3行用来实现行用来实现a和和b的值互换的值互换a=b;b=temp;运行时输出运行时输出3 5i和和j的值并未互换。见图的值并未互换。见图6.27示意。示意。为了解决这个问题,采用传递变量地址的方法。为了解决这个问题,采用传递变量地址的方法。图图6.27(2) 传递变量的指针。传递变量的指针。形参是指针变量,实参是一个形参是指针变量,实参是一个变量的地

49、址,调用函数时,形参变量的地址,调用函数时,形参(指针变量指针变量)指向实参指向实参变量单元。程序见例变量单元。程序见例6.19。例例6.19 使用指针变量作形参,实现两个变量的值互换。使用指针变量作形参,实现两个变量的值互换。#include using namespace std;int main( ) void swap(int *,int *);int i=3,j=5;swap(&i,&j); /实参是变量的地址实参是变量的地址couti jendl; /i和和j的值已互换的值已互换return 0;void swap(int *p1,int *p2) /形参是指针变量形参是指针变量

50、int temp;temp=*p1; /以下以下3行用来实现行用来实现i和和j的值互换的值互换*p1=*p2;*p2=temp;形参与实参的结合见图形参与实参的结合见图6.28示意。示意。图图6.28这种虚实结合的方法仍然是这种虚实结合的方法仍然是“值传递值传递”方式,只是实方式,只是实参的值是变量的地址而已。通过形参指针变量访问主参的值是变量的地址而已。通过形参指针变量访问主函数中的变量函数中的变量(i和和j),并改变它们的值。这样就能得并改变它们的值。这样就能得到正确结果,但是在概念上却是兜了一个圈子,不那到正确结果,但是在概念上却是兜了一个圈子,不那么直截了当。么直截了当。C+提供了向函

51、数传递数据的第提供了向函数传递数据的第(3)种方法,即传送变量的别种方法,即传送变量的别名。名。例例6.20 利用利用“引用形参引用形参”实现两个变量的值互换。实现两个变量的值互换。#include using namespace std;int main( ) void swap(int &,int &);int i=3,j=5;swap(i,j);couti=i j=jendl;return 0;void swap(int &a,int &b) /形参是引用类型形参是引用类型 int temp;temp=a;a=b;b=temp;输出结果为输出结果为i=5 j=3在在swap函数的形参表列

52、中声明函数的形参表列中声明a和和b 是整是整型变量的引用。型变量的引用。图图6.29实际上,在虚实结合时是把实参实际上,在虚实结合时是把实参i的地址传到形参的地址传到形参a,使形参使形参a的地址取实参的地址取实参i的地址,从而使的地址,从而使a和和i共享同一共享同一单元。同样,将实参单元。同样,将实参j的地址传到形参的地址传到形参b,使形参使形参b的的地址取实参地址取实参j的地址,从而使的地址,从而使b和和j共享同一单元。这共享同一单元。这就是地址传递方式。就是地址传递方式。为便于理解,可以通俗地说:为便于理解,可以通俗地说: 把变量把变量i的名字传给引用变量的名字传给引用变量a,使使a成为成

53、为i的别名。的别名。例例6.21 对对3个变量按由小到大的顺序排序。个变量按由小到大的顺序排序。#include using namespace std;int main( ) void sort(int &,int &,int &); /函数声明,形参是引用类型函数声明,形参是引用类型int a,b,c; /a,b,c是需排序的变量是需排序的变量int a1,b1,c1; /a1,b1,c1最终的值是已排好序的数列最终的值是已排好序的数列coutabc; /输入输入a,b,ca1=a;b1=b;c1=c; sort(a1,b1,c1); /调用调用sort函数,以函数,以a1,b1,c1为实

54、参为实参coutsorted order is a1 b1 c1j) change (i,j); /使使ik) change (i,k); /使使ik) change (j,k); /使使j=k void change (int &x,int &y) /使使x和和y互换互换 int temp;temp=x;x=y;y=temp;运行情况如下:运行情况如下: Please enter 3 integers: 23 12 -345 sorted order is -345 12 23 可以看到:可以看到: 这个程序很容易理解,不易出错。由于这个程序很容易理解,不易出错。由于在调用在调用sort函数

55、时虚实结合使形参函数时虚实结合使形参i,j,k成为实参成为实参a1,b1,c1的引用的引用,因此通过调用函数,因此通过调用函数sort(a1,b1,c1)既既实现了对实现了对i,j,k排序,也就同时实现了对排序,也就同时实现了对a1,b1,c1排序。排序。同样,执行同样,执行change (i,j)函数,可以实现对实参函数,可以实现对实参i和和j的的互换。互换。引用不仅可以用于变量,也可以用于对象。例如实参引用不仅可以用于变量,也可以用于对象。例如实参可以是一个对象名,在虚实结合时传递对象的起始地可以是一个对象名,在虚实结合时传递对象的起始地址。这会在以后介绍。址。这会在以后介绍。当看到当看到&a这样的形式时,怎样区别是声明引用变量还这样的形式时,怎样区别是声明引用变量还是取地址的操作呢?当是取地址的操作呢?当&a的前面有类型符时(如的前面有类型符时(如int &a),),它必然是对引用的声明;如果前面无类型符它必然是对引用的声明;如果前面无类型符(如(如cout&a),),则是取变量的地址。则是取变量的地址。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 资格认证/考试 > 自考

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