第7章_指针C++_第1页
第7章_指针C++_第2页
第7章_指针C++_第3页
第7章_指针C++_第4页
第7章_指针C++_第5页
已阅读5页,还剩113页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1第7章 指针与引用第7章 指 针2第7章 指针与引用思考: A、B、C三人欲借用旅馆的房间。A先到达旅馆,在服务台登记了房间,房号是5818。然后A电话通知了B,但没有通知C。 B和C该怎样找到A呢?方法:B可以直接到5818找到A。 C可以到旅馆的服务台查询到A的房间号是 5818,再找到A。3第7章 指针与引用7.1 指针与指针变量7.2 指针的使用及运算7.3 指针与数组7.4 指针与字符串7.5 指针与函数7.6 动态内存7.7 带参数的main函数*7.8 引用类型47.1 指针与指针变量可以按变量名称直接访问内存单元,也可以通过指针间接访问内存单元。当两个函数相互之间要访问数据时

2、,由于函数内部数据互不可视,只能通过指针间接访问(直接访问做不到了)本章的指针有许多让初学者头疼的复杂形式和复杂概念,请牢记:之所以有如此多的复杂形式,是因为函数参数传递具有如此多的复杂形式57.1.1 地址和指针的概念程序中的数据对象总是存放在内存中,在生命期内这些对象占据一定的存储空间,有确定的存储位置。实际上,每个内存单元都有一个地址,即以字节为单位连续编码。编译器将程序中的对象名转换成机器指令能识别的地址,通过地址来存取对象值。67.1.1 地址和指针的概念图7.1 变量的内存形式int int i i; ; /定义整型变量定义整型变量double double f f; ; /定义双

3、精度浮点型变量定义双精度浮点型变量按对象名称存取对象的方式称为对象直接访问。一个对象的地址称为该对象的指针。通过对象地址存取对象的方式称为指针间接访问。1005.04000if40004500P77.1.2 指针变量C+将专门用来存放对象地址的变量称为指针变量,定义形式如下:例如:指针类型指针类型 * *指针变量名指针变量名,.,.int int * *p1p1, , * *p2p2; ; /定义定义p1p1和和p2p2为指针变量为指针变量int int * *p p, , k k; ; /定义定义p p为指针变量,为指针变量,k k为整型变量为整型变量通过指针变量,可以间接访问(或间接存取)

4、对象。87.1.2 指针变量图7.2 通过指针变量间接访问97.1.2 指针变量图7.3 指向类型的含义假定指针变量p的值是4000,下面三种写法char char * *p p; ;int int * *p p; ;double double * *p p; ;107.2 指针的使用及运算获取变量的地址可以通过取地址运算(&)获取对象的地址。117.2.1 获取对象的地址表7-1 取地址运算符int int a a= =2020, , * *p p; ; /定义指针变量定义指针变量p p = &= &a a ; ; /指针变量指针变量p p指向指向a a图7.4 &运算的含义127.2.1

5、获取对象的地址例7.1 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int i i= =400400; ; 6 couti=i,&i=&i couti=i,&i=&iendlendl; ; 7 return return 0 0; ; 8 137.2.1 获取对象的地址例7.1 1 #include #include 2 using namespace std;using namespace std; 3 int main()int main()

6、4 5 int i=400; int i=400; 6 couti=i,&i=&iendl; couti=i,&i=&iendl; 7 return 0; return 0; 8 i=400,&i=0012FF7C程序运行屏幕147.2.2 指针的间接访问表7-2 间接引用运算符指针的间接访问通过间接引用运算(*)可以访问指针所指向的对象或内存单元157.2.2 指针的间接访问图7.5 *运算的含义int int a a, , * *p=&ap=&a; ;a a= =100100; ; /直接访问直接访问a a(对象直接访问)(对象直接访问)* *p p= =100100; ; /* *p p

7、就是就是a a,间接访问,间接访问a a(指针间接访问)(指针间接访问)* *p=p=* *p p+ +1 1; ; /等价于等价于a=a+1a=a+1167.2.2 指针的间接访问【例7.2】 已知:则&*p1的含义是什么?*&a的含义是什么?int int a a, , b b, , * *p1=&ap1=&a, , * *p2p2; ;&*p1 p1 &a*&a a *p177.2.2 指针的间接访问例7.3 1 int int main()main() 2 3 int int i i= =100100, , j j= =200200; ; 4 int int * *p1p1, , *

8、*p2p2; ; 5 p1=&i p1=&i, , p2=&jp2=&j; ; /p1/p1指向指向i i,p2p2指向指向j j 6 * *p1 p1 = = * *p1 p1 + + 1 1; ; /等价于等价于i=i+1i=i+1 7 p1 p1= =p2p2; ; /将将p2p2的值赋值给的值赋值给p1p1,则,则p1p1指向指向j j 8 * *p1 p1 = = * *p1 p1 + + 1 1; ; /等价于等价于j=j+1j=j+1 9 return return 0 0; ; 10 187.2.2 指针的间接访问例7.4 1 # #include include 2 usin

9、g namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int a a, ,b,b,* *p,p,* *p1,p1,* *p2p2; ; 6 p1=&a p1=&a, , p2=&bp2=&b; ; /p1/p1指向指向a a,p2p2指向指向b b 7 cin cin* *p1p1* *p2p2; ; 8 ifif( (* *p1p1* *p2) pp2) p= =p1p1, , p1p1= =p2p2, , p2p2= =p p; ; 9 couta=a,b=b couta=a,b=bendlendl; ;

10、10 coutmin= coutmin=* *p1,max=p1,max=* *p2p2endlendl; ; 11 return return 0 0; ; 12 197.2.2 指针的间接访问图7.7 指针交换示意207.2.3 指针变量的初始化与赋值可以在定义指针变量时对其初始化,一般形式为:指针类型指针类型 * *指针变量名指针变量名= =地址初值地址初值,.,.int int a a; ;int int * *p=&ap=&a; ; /p/p的初值为变量的初值为变量a a的地址的地址int int b b, , * *p1=&bp1=&b; ; /正确,正确,p1p1初始化时变量初始

11、化时变量b b已有地址值已有地址值复习:指针的定义:专门用来存放地址的变量指针的类型:int *p; double *q; char *t;间接引用:int a, *p=&a; *p=100; 21227.2.3 指针变量的初始化与赋值由于指针数据的特殊性,其初始化和赋值运算是有约束条件的,只能使用以下四种值:(1)0值常量表达式,例如:int int a a, , z z= =0 0; ;int int * *p1p1= =a a; ; /错误错误,地址初值不能是变量,地址初值不能是变量p1p1= =z z; ;/错误错误,整型变量不能作为指针,即使值为,整型变量不能作为指针,即使值为0 0

12、p1p1= =40004000; ; /错误错误,整型数据不能作为指针,整型数据不能作为指针p1p1= =nullnull; ; /正确,指针允许正确,指针允许0 0值常量表达式值常量表达式p1p1= =0 0; ; /正确,指针允许正确,指针允许0 0值常量表达式值常量表达式237.2.3 指针变量的初始化与赋值(2)相同指向类型的对象的地址。例如:int int a a, , * *p1p1; ;double double f f, , * *p3p3; ;p1=&ap1=&a; ; /正确正确p3=&fp3=&f; ; /正确正确p1=&fp1=&f; ; /错误错误,p1p1和和&f&

13、f指向类型不相同指向类型不相同247.2.3 指针变量的初始化与赋值(3)相同指向类型的另一个有效指针。例如:(4)对象存储空间后面下一个有效地址,如数组下一个元素的地址。int int x x, , * *px=&xpx=&x; ; /正确正确int int * *pypy= =pxpx; ; /正确,相同指向类型的另一个指针正确,相同指向类型的另一个指针double double * *pzpz; ;pypy= =pxpx; ; /正确,相同指向类型的另一个指针正确,相同指向类型的另一个指针pzpz= =pxpx; ; /错误错误,pzpz和和pxpx指向类型不相同指向类型不相同257.2

14、.4 指针的有效性指针指向一个有确定存储空间的对象(称为已知对象),则该指针是有效的;即如果对该指针使用间接引用运算,总能够得到这个已知对象。指针理论上可以为任意的地址值,若一个指针不指向程序中任何已知对象,称其指向未知对象。未知对象的指针是无效的,无效的指针使用间接引用运算几乎总会导致崩溃性的异常错误。267.2.4 指针的有效性(1)如果指针的值为0,称为0值指针,又称空指针(null pointer),空指针是无效的。(2)如果指针未经初始化,或者没有赋值,称为野指针,那么该指针是无效的。int int * *p p= =0 0; ;* *p p= =2 2; ; /空指针间接引用将导致

15、程序产生严重的异常错误空指针间接引用将导致程序产生严重的异常错误int int * *p p; ;* *p p= =100100; ; / /错误错误,p p为无效指针,不能间接引用为无效指针,不能间接引用277.2.4 指针的有效性一个指针还没有初始化,称为“野指针”(wild pointer),大多数的编译器都对此产生警告。例如:一个指针曾经指向一个已知对象,在对象的内存空间释放后,虽然该指针仍是原来的内存地址,但指针所指已是未知对象,称为“迷途指针”(dangling pointer)。例如:int int * *p p; ; /p/p是野指针是野指针* *p p= =2 2; ; /几

16、乎总会导致程序产生严重的异常错误几乎总会导致程序产生严重的异常错误287.2.4 指针的有效性char char * *p p= =NULLNULL; ; /p/p是空指针,全局变量是空指针,全局变量void void fun()fun() char char c c; ; /局部变量局部变量 p p = &= &c c; ; /指向局部变量指向局部变量c c,函数调用结束后,函数调用结束后,c c的空间释放,的空间释放,p p就成了迷途指针就成了迷途指针 void void caller()caller() fun(); fun(); * *p p= =2 2; ; /p p现在是迷途指针现

17、在是迷途指针 297.2.5 指针运算(1)指针加减整数运算设p是一个指针,n是一个整型量,则p+n的结果是一个指针,指向p所指向对象的后面的第n个对象;而p-n的结果是一个指针,指向p所指向对象的前面的第n个对象。int int x x, , n n= =3 3 , , * *p=&xp=&x; ;p p+ +1 1 /指向存储空间中变量指向存储空间中变量x x后面的第后面的第1 1个个intint型存储单元型存储单元p p+ +n n /指向存储空间中变量指向存储空间中变量x x后面的第后面的第n(3)n(3)个个intint型存储单元型存储单元p p- -1 1 /指向存储空间中变量指向

18、存储空间中变量x x前面的第前面的第1 1个个intint型存储单元型存储单元p p- -n n /指向存储空间中变量指向存储空间中变量x x前面的第前面的第n(3)n(3)个个intint型存储单元型存储单元307.2.5 指针运算例7.5 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int x x, , n n= =3 3, , * *p=&xp=&x; ; 6 coutp=hex coutp=hexp,pp,p+ +1=p1=p+ +1, ;

19、 1, ; /地址输出用十六进制形式地址输出用十六进制形式 7 cout“p cout“p+ +n=”hexn=”hexp p+ +n“,pn“,p- -n=”pn=”p- -n nendlendl; ; /地址输出用十六进制形式地址输出用十六进制形式 8 return return 0 0; ; 9 317.2.5 指针运算(2)指针变量自增自减运算设p是一个指针变量,其自增自减运算包括p+、+p、p-、-p形式。327.2.5 指针运算int int x x, , * *p=&xp=&x; ;p p+ + /运算后表达式的值指向变量运算后表达式的值指向变量x x,p p指向变量指向变量x

20、x后面的第后面的第1 1个个intint型内存单元型内存单元+p p /运算后表达式的值和运算后表达式的值和p p均指向变量均指向变量x x后面的第后面的第1 1个个intint型内存型内存单元单元p p- - /运算后表达式的值指向变量运算后表达式的值指向变量x x,p p指向变量指向变量x x前面的第前面的第1 1个个intint型内存单元型内存单元-p p /运算后表达式的值和运算后表达式的值和p p均指向存储空间中变量均指向存储空间中变量x x前面的第前面的第1 1个个intint型内存单元型内存单元337.2.5 指针运算例7.6 1 # #include include 2 usi

21、ng namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int x x, , * *p1p1, , * *p p; ; 6 p=&x p=&x , , p1p1= =p+;p+; 7 coutp+: coutp+: & &x=hex&x, p=p, x=hex&x, p=p, p1=p1p1=p1endlendl; ; 8 p=&x p=&x , , p1=+pp1=+p; ; 9 cout“+p cout“+p: &: &x=”hex&x“, p=”p“, x=”hex&x“, p=”p“, 平平p1=p1p

22、1=p1 b b /正确,表示两个地址的比较,而非两个数组内容的比较正确,表示两个地址的比较,而非两个数组内容的比较487.3.1 指向一维数组元素的指针2指向一维数组元素的指针变量定义指向一维数组元素的指针变量时,指向类型应该与数组元素类型一致,例如:int int a10, a10, * *p1p1; ;double double f10, f10, * *p2p2; ;p1p1= =a a; ; /正确正确p2p2= =f f; ; /正确正确p1p1= =f f; ; /错误错误,指向类型不同不能赋值,指向类型不同不能赋值497.3.1 指向一维数组元素的指针3通过指针访问一维数组元素

23、由于数组元素的地址是规律性增加的,根据指针算术运算规则,可以利用指针及其运算来访问数组元素。设有如下定义:int int * *p p, , a10=1a10=1, ,2 2, ,3 3, ,4 4, ,5 5, ,6 6, ,7 7, ,8 8, ,9 9, ,10;10;p p= =a a; ; /p/p指向数组指向数组a ap+p+; ;507.3.1 指向一维数组元素的指针图7.11 指向一维数组的指针设:a是一维数组名,p是指针变量且p=a。根据以上叙述,访问一个数组元素ai,可以用:数组下标法:ai;指针下标法:pi;地址引用法:*(a+i);指针引用法:*(p+i)。517.3.

24、1 指向一维数组元素的指针例7.8 用多种方法遍历一维数组元素 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int a10, ia10, i; ; 6 for for (i(i= =0 0; ;i i a a i;i; 7 for for (i(i= =0 0; ;i i 1010; ;i+) couti+) couta a i ;i ; 8 return return 0 0; ; 9 下标法。527.3.1 指向一维数组元素的指针 1 # #i

25、nclude include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int a10, ia10, i; ; 6 for for (i(i= =0 0; ;i i i+) cin* *(a(a+ +i);i); 7 for for (i(i= =0 0; ;i i 1010; ;i+) couti+) cout* *(a(a+ +i) ;i) ; 8 return return 0 0; ; 9 通过地址间接访问数组元素。537.3.1 指向一维数组元素的指针 1 # #include

26、 include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 int int a10, a10, * *p p; ; 6 for for (p(p= =a a; ;p p p+) cin* *p p; ; 7 for for (p(p= =a a; ;p p a a+ +1010; ;p+) coutp+) cout* *p ;p ; 8 return return 0 0; ; 9 通过指向数组的指针变量间接访问元素。547.3.1 指向一维数组元素的指针4数组元素访问方法的比较(1)使用下标法

27、访问数组元素,程序写法比较直观,能直接知道访问的是第几个元素。(2)下标法与地址引用法运行效率相同。而使用指针引用法,指针变量直接指向元素,不必每次都重新计算地址,能提高运行效率。557.3.1 指向一维数组元素的指针(3)ai和pi的运行效率相同,但两者还是有本质的区别。数组名a是数组元素首地址,它是一个常量,其值在程序运行期间是固定不变的。(4)将自增和自减运算用于指针变量十分有效,可以使指针变量自动向前或向后指向数组的下一个或前一个元素。567.3.1 指向一维数组元素的指针(5)需要注意指针变量各种运算形式的含义。*p+。*(p+)和*(+p)不同。(*p)+表示p所指向的元素加1。a

28、*(p+)等价于ai+;b*(+p)等价于a+i;c*(p-)等价于ai-;d*(-p)等价于a-i。577.4 指针与字符串可以利用一个字符型的指针处理字符数组和字符串,其过程与通过指针访问数组元素相同。使用指针可以简化字符串的处理,是程序员处理字符串常用的编程方法。587.4.1 指向字符串的指针可以定义一个字符数组,用字符串常量初始化它,例如:系统会在内存中创建一个字符数组str,且将字符串常量的内容复制到数组中,并在字符串末尾自动增加一个结束符0。char char str=C Language;str=C Language;597.4.1 指向字符串的指针C+允许定义一个字符指针,初

29、始化时指向一个字符串常量,一般形式为:charchar * *字符字符指针变量指针变量= =字符串常量字符串常量,.,.char char * *p=C Language;p=C Language;char char * *p p; ;p=C Language; p=C Language; 初始化时,p存储了这个字符串首字符地址4000,而不是字符串常量本身,称p指向字符串。607.4.1 指向字符串的指针图7.19 指向字符串的指针617.4.1 指向字符串的指针通过字符指针可以访问字符串。例如:char char str=C Language, str=C Language, * *p p

30、= =strstr; ; /p/p指向字符串的指针指向字符串的指针coutcoutp pendlendl; ; /输出:输出:C LanguageC Languagecoutcoutp p+ +2 2endlendl; ; /输出:输出:LanguageLanguagecout&str7endlcout&str7endl; ; /输出:输出:ageage627.4.1 指向字符串的指针通过字符指针遍历字符串。char char str=C Language, str=C Language, * *p p= =strstr; ; /p/p指向字符串的指针指向字符串的指针while while (

31、 (* *p p!=!=0) cout0) cout* *p+;p+;637.4.1 指向字符串的指针例7.15 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 char char str100,str100,* *p p= =strstr; ; 6 cin cinstrstr; ; /输入字符串输入字符串 7 while while ( (* *p) p+; p) p+; /指针指针p p指向到字符串结束符指向到字符串结束符 8 coutstrlen=p c

32、outstrlen=p- -strstrendlendl; ; 9 return return 0 0; ; 10 647.4.1 指向字符串的指针例7.15 1 #include #include 2 using namespace std;using namespace std; 3 int main()int main() 4 5 char str100, char str100,* *p=str;p=str; 6 cinstr; / cinstr; /输入字符串输入字符串 7 while ( while (* *p) p+; /p) p+; /指针指针p p指向到字符串结束符指向到字符

33、串结束符 8 coutstrlen=p-strendl; coutstrlen=p-strendl; 9 return 0; return 0; 10 strlen=10程序运行屏幕JavaScript657.4.1 指向字符串的指针图7.20 指针相减的含义667.4.2 指针与字符数组的比较1存储内容不同2运算方式不同3赋值操作不同char char s100=Computer;s100=Computer;char char * *p=Computer;p=Computer;s=C+; s=C+; /错误错误s+; s+; /错误错误s0=Cs0=C; ; /正确正确p=C+; p=C+;

34、 /正确正确* *p p= =CC; ; /正确正确p+; p+; /正确正确677.4.2 指针与字符数组的比较例7.16 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4 5 char char * *p=VisualBasic;p=VisualBasic; 6 int int i i= =0 0; ; 7 while while (pi) cout(pi) coutp p i+i+ ; ; 8 return return 0 0; ; 9 687.4.3 指向

35、字符串数组的指针字符串数组是一个二维字符数组,例如:char char sa67=C+,Java,C,PHP,sa67=C+,Java,C,PHP, CSharp,Basic; CSharp,Basic;697.4.3 指向字符串数组的指针图7.21 字符串数组的内存形式C+程序员更偏爱使用指针来访问数组元素,这样做的好处是运行效率高、写法简洁。复习:设:a是一维数组名,p是指针变量且p=a。数组元素ai 可以表示为:pi、*(a+i)、*(p+i)。ai的地址可以表示为:&ai、a+i、p+i 71 1 # #include include 2 using namespace using n

36、amespace stdstd; ; 3 int int main()main() 4 5 int int a10, ia10, i; ; 6 for for (i(i= =0 0; ;i i ai;ai; 7 for for (i(i= =0 0; ;i i 1010; ;i+) couti+) coutai ;aicin* *(a(a+ +i);i);coutcout* *(a(a+ +i) “;i) “;72 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4

37、5 int int a10, a10, * *p p; ; 6 for for (p(p= =a a; ;p p p+) cin* *p p; ; 7 for for (p(p= =a a; ;p p a a+ +1010; ;p+) coutp+) cout* *p ;p ; 8 return return 0 0; ; 9 复习:73使用字符指针处理字符串可以简化字符串的处理,是程序员处理字符串常用的编程方法。 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int main()main() 4

38、5 char char * *p=VisualBasic;p=VisualBasic; 6 int int i i= =0 0; ; 7 while while (pi) cout(pi) coutp p i+i+ ; ; 8 return return 0 0; ; 9 复习:747.5 指针与函数指针最重要的应用是作为函数参数,它使得被调函数除了返回值之外,能够将更多的运算结果返回到主调函数中指针是函数参数传递的重要工具。757.5.1 指针作为函数参数1指针变量作为函数形参函数形参可以是指针类型,一般形式为:返回类型 函数名(指向类型 *指针变量名,.)函数体 767.5.1 指针作为函

39、数参数例7.18 1 # #include include 2 using namespace using namespace stdstd; ; 3 void void swap(swap(int int * *p1p1, , int int * *p2)p2) 4 5 int int t t; ; 6 t= t=* *p1 p1 , , * *p1=p1=* *p2p2, , * *p2p2= =t t; ; 7 8 int int main()main() 9 10 int int a a, , b b; ; 11 cin cina ab b; ; 12 swap(&a swap(&a,

40、 , &b);&b); 13 coutmin=a,max=b coutmin=a,max=a ab b; ; 12 swap(&a swap(&a, , &b);&b); 13 return 0; return 0; 14 int int * *t;t;t=p1 , p1=p2, p2=t;t=p1 , p1=p2, p2=t;797.5.1 指针作为函数参数通过将指针作为函数参数的方法,既可以返回多个运算结果,又避免了使用全局变量。807.5.1 指针作为函数参数例7.19 计算a和b的平方和、自然对数和、几何平均数、和的平方根 1 # #include include 2 # #inclu

41、de include 3 using namespace using namespace stdstd; ; 4 double double fun(fun(double double a a, ,double double b b, ,double double * *sqabsqab, , double double * *lnablnab, , double double * *avg)avg) 5 6 * *sqabsqab= =a a* *a a+ +b b* *b b; ; * *lnablnab= =log(a)+log(b);log(a)+log(b); 8 * *avg=(a

42、avg=(a+ +b)/2b)/2; ; 9 return return (sqrt(a(sqrt(a+ +b);b);/函数返回和的平方根函数返回和的平方根 10 11 int int main()main() 12 13 double double x x= =1010, ,y y= =1212, ,fsqfsq, ,flnfln, ,favgfavg, ,fsqrfsqr; ; 14 fsqr fsqr= =fun(xfun(x, , y y, &, &fsqfsq, &, &flnfln, &, &favg);favg); 15 cout coutx,y,fsq,flnx,y,fsq,

43、fln ,favg,fsqr ,favg,fsqrendlendl; ; 16 return return 0 0; ; 17 817.5.1 指针作为函数参数2数组作为函数形参(一维或多维)数组作为函数的形参,例如:函数调用形式如下:double double average(average(double double * *a, a, int int n)n) /函数体函数体 double double X100, fX100, f; ;f f = = average(Xaverage(X, , 100);100);827.5.1 指针作为函数参数例7.20 编写函数average,返回数

44、组n个元素的平均值。 1 # #include include 2 using namespace using namespace stdstd; ; 3 double double average(average(double double * *a a, , int int n)n) 4 5 double double avgavg= =0 0. .0 0, , * *p p= =a a; ; 6 int int i i; ; 7 for for (i(i= =1 1; ;i i=n n; ;i+,p+) avgi+,p+) avg= =avg avg + + * *p p; ; 8 re

45、turn return n n=0 0 ? ? 0 0 : : avgavg/ /n n ; ; 9 837.5.1 指针作为函数参数例7.20 10 int int main()main() 11 12 double double x10=66x10=66, ,7676. .5 5, ,8989, ,100100, ,7171. .5 5, , 8686, ,9292, ,9090. .5 5, ,7878, ,88;88; 13 coutaverage=average(x coutaverage=average(x, ,10)endl10)endl; ; 14 return return

46、0 0; ; 15 847.5.1 指针作为函数参数要想在子函数中改变主调函数中的数组元素,实参与形参的对应关系有如下4种,这4种情况作用相同。(1)形参和实参都用数组名,例如:(2)形参用指针变量,实参用数组名,例如:void void fun(fun(int int x100, x100, int int n); n); /函数原型函数原型int int a100;a100;fun(afun(a, , 100); 100); /函数调用函数调用void void fun(fun(int int * *x x, , int int n); n); /函数原型函数原型int int a100;

47、a100;fun(afun(a, , 100); 100); /函数调用函数调用857.5.1 指针作为函数参数(3)形参与实参都用指针变量,例如:(4)形参用数组,实参用指针变量,例如:void void fun(fun(int int * *x x, , int int n); n); /函数原型函数原型int int a100, pa100, p= =a a; ;fun(pfun(p, , 100); 100); /函数调用函数调用void void fun(fun(int int x100, x100, int int n); n); /函数原型函数原型int int a100, pa

48、100, p= =a a; ;fun(pfun(p, , 100); 100); /函数调用函数调用867.5.1 指针作为函数参数4字符指针变量作为函数形参将一个字符串传递到函数中,传递的是地址,则函数形参既可以用字符数组,又可以用指针变量,两种形式完全等价。在子函数中可以修改字符串的内容,主调函数得到的是变化后的字符串。877.5.1 指针作为函数参数例7.21 自定义函数实现strcpy函数的字符串复制功能 1 # #include include 2 using namespace using namespace stdstd; ; 3 char char * *stringcpy(s

49、tringcpy(char char * *strDeststrDest, , const char const char * *strSrc)strSrc) 4 5 char char * *p1p1= =strDeststrDest; ; 6 const char const char * *p2p2= =strSrcstrSrc; ; 7 while while ( (* *p2p2!=!=0 0 ) ) 8 * *p1=p1=* *p2p2, , p1p1+ , + , p2p2+; ; 9 * *p1p1=00; ; 10 return return strDeststrDest;

50、; /返回实参指针返回实参指针 11 887.5.1 指针作为函数参数例7.21 11 int int main()main() 12 13 char char s180,s280,s380=string=;s180,s280,s380=string=; 14 cin cins1s1; ; /输入字符串输入字符串 15 stringcpy(s2 stringcpy(s2, ,s1); s1); /复制复制s1s1到到s2s2 16 couts2:s2 couts2:s2endlendl; ; 17 stringcpy(&s37,s1); stringcpy(&s37,s1);/复制复制s1s1

51、到到s3s3的后面的后面 18 couts3:s3 couts3:s3endlendl; ; 19 return return 0 0; ; 20 7.5.3 函数指针C+允许定义指向函数的指针变量,定义形式为:它可以指向形如返回类型 (*函数指针变量名)(形式参数列表),.;返回类型 函数名(形式参数列表)函数体 int int ( (* *p)(p)(int int a a, , int int b); b); /定义函数指针变量定义函数指针变量7.5.3 函数指针1指向函数可以将函数的地址赋值给函数指针变量,形式为它要求函数指针变量与指向函数必须有相同的返回类型、参数个数、参数类型。函数

52、指针变量函数指针变量= =函数名函数名; ;7.5.3 函数指针例如假设:则称p指向函数max。它也可以指向函数min,即可以指向所有与它有相同的返回类型、参数个数、参数类型的函数。int int max(max(int int a a, , int int b); b); /max/max函数原型函数原型int int min(min(int int a a, , int int b); b); /min/min函数原型函数原型int int ( (* *p)(p)(int int a a, , int int b); b); /定义函数指针变量定义函数指针变量p p= =maxmax; ;

53、7.5.3 函数指针2通过函数指针调用函数对函数指针间接引用即是通过函数指针调用函数,一般形式为:两种形式是完全相同的。通常,程序员偏爱用第种形式。通过函数指针调用函数,在实参、参数传递、返回值等方面与函数名调用相同。例如:(*函数指针)(实参列表)函数指针(实参列表)c c= =p(ap(a, ,b); b); /等价于等价于c=max(a,b);c=max(a,b);7.5.3 函数指针例7.23 1 # #include include 2 using namespace using namespace stdstd; ; 3 int int max(max(int int a a, ,

54、 int int b) b) /求最大值求最大值 4 5 return return a a b b ? ? a a: :b b ; ; 6 7 int int min(min(int int a a, , int int b) b) /求最小值求最小值 8 9 return return a a b b ? ? a a: :b b ; ; 10 7.5.3 函数指针例7.23 11 int int main()main() 12 13 int int ( (* *p)(p)(int int a a, ,int int b);b);/定义函数指针变量定义函数指针变量 14 p p= =maxm

55、ax; ; /p/p指向指向maxmax函数函数 15 cout coutp(3p(3, ,4) ; 4) ; /通过通过p p调用函数调用函数 16 p p= =minmin; ; /p/p指向指向minmin函数函数 17 cout coutp(3p(3, ,4) ; 4) ; /通过通过p p调用函数调用函数 18 return return 0 0; ; 19 从中看出,函数调用p(3,4)究竟调用max或者min,取决于调用前p指向哪个函数。7.5.3 函数指针3函数指针的用途指向函数的指针多用于指向不同的函数,从而可以利用指针变量调用不同函数,相当于将函数调用由静态方式(固定地调用

56、指定函数)变为动态方式(调用哪个函数是由指针值来确定)。熟练掌握函数指针的应用,有利于程序的模块化设计,提高程序的可扩展性。7.5.3 函数指针函数指针变量可以作为函数形参,此时实参要求是函数名(即函数地址),或者是函数指针,而形参和实参有相同的返回类型、参数个数、参数类型。7.5.3 函数指针232(1)xbbbaaax dxedxx dx【例7.24】 编写程序计算如下公式。说明:这里用梯形法求定积分 的近似值。如图所示,求 f(x)的定积分就是求f(x)曲线与x轴包围图形的面积,梯形法是把所要求的面积垂直分成n个小梯形,然后面积求和。( )baf x dx7.5.3 函数指针图7.24

57、梯形法求定积分示意7.5.3 函数指针根据上述思想编写函数integral,由于需要计算多个不同f(x)的值,因此向integral传递f(x)的函数指针,由integral回调具体的f(x)求值,其函数原型为:在integral中通过函数指针f调用传进去的具体函数,即称为回调。double double integral(integral(double double a a, ,double double b b, , double double ( (* *f)(f)(double double x) x) /求定积分求定积分7.5.3 函数指针例7.24 1 # #include inc

58、lude 2 # #include include 3 using namespace using namespace stdstd; ; 4 double double integral(integral(double double a a, ,double double b b, , double double ( (* *f)(f)(double double x) x) /求定积分求定积分 5 6 int int n n= =10001000, , i i; ; 7 double double h h, , x x, , s s= =0 0. .0 0; ; 8 h=(b h=(b-

59、-a)/na)/n; ; 9 forfor(i(i= =1 1; ;i i=a ab b; ; 28 cout(integral(a cout(integral(a, ,b b, ,f1)+f1)+ integral(a integral(a, ,b b, ,f2)+integral(af2)+integral(a, ,b b, ,f3)f3) endl endl; ; 29 return return 0 0; ; 30 103*7.8 引用类型通过对象名称直接访问对象,优点是直观,操作哪个对象一目了然,缺点是由于对象名存在作用域的限制,某些情况下是不能按名称访问对象的,例如一个函数内部不能

60、使用另一个函数的局部变量;通过指针(或地址)间接访问对象,优点是无所不能,缺点是程序中大量出现的间接访问,实在分不清具体是哪个对象,需要通过上下文去分析。C+扩充了C语言对象访问方式,提供了引用访问。通过引用访问对象,结合了按名访问和按地址访问各自的优点,非常适合作为函数参数。1047.8.1 引用的概念与定义简单地说,引用(reference)就是一个对象的别名(alias name),其声明形式为:在C+中,引用全部是const类型,声明之后不可更改(即不能再是别的对象的引用)。引用类型引用类型 & &引用名称引用名称= =对象名称对象名称 , .;, .;int int x x; ; /

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论