1、 如何上大学?9/26/20241 9/26/20242高高高高 等等等等 教教教教 育育育育 出出出出 版版版版 社社社社 20042004年第年第年第年第2 2版版版版 高级语言高级语言C+程序设计程序设计 第第 6 章章 指针,引用与动态内存分配指针,引用与动态内存分配 9/26/20243 本章重点本章重点 指针类型的使用指针类型的使用;指针与数组指针与数组 与与 字符串指针;字符串指针;指针与函数指针与函数;指针作参数,指针函数;指针作参数,指针函数 指针与动态内存分配指针与动态内存分配;new 与与 delete 导出数据类型:引用类型变量导出数据类型:引用类型变量.9/26/20
2、244一一.指针指针 -指针即地址指针即地址.int a10,*p1=a;地址地址 char str100,*p2=str;float x,*p3=&x;2001 2002 1.内存单元和地址内存单元和地址 2003 2004 内存单元-存放数据的内存空间 地址-内存单元的顺序编号2008内存单元 65 0000 0101 0000 0000 0000 1010 0000 0000 0000 0000 0000 0000 char c=A;long b=10;float x=1.0 int a=5;6.1 指指 针针 9/26/20245 2.变量与地址变量与地址变量的地址:变量的地址:&c=
3、2001&a=2002&b=2004&x=2008变量名变量名数据类型数据类型变量地址 C char 2001 a int 2002 b long 2004 x float 20089/26/202463.数组与地址数组与地址 -“数组名即地址数组名即地址”int array3=1,2,3;3210 array0 数组与地址对照表数组与地址对照表 3212 数组名数组名 数据类型数据类型 长度长度 首地址首地址 array1 array int 3 3210 3214 array2数组首地址数组首地址=array0;数组元素数组元素 arrayi =数组首地址数组首地址+i *数据类型长度数据
4、类型长度 的地址的地址0000000100000000000000100000000000000011000000009/26/20247二二.指针变量指针变量-取值为内存地址的变量。取值为内存地址的变量。1.指针变量的取值指针变量的取值-指针变量占用指针变量占用 2 个字节,存放个字节,存放 16位位的的 内存地址内存地址。例:例:int a=5,*p;地址地址 p=&a;2002 00000101 00000000 2.指针变量的作用指针变量的作用 -直接访问内存,直接访问内存,实现数据的读写。实现数据的读写。.改变不同的值,访问不同的单元改变不同的值,访问不同的单元例:例:cin *p;
5、xxxx2002 p=&a;*p=10;(变量变量 a 的值变为的值变为 10)9/26/20248一一.指针变量的定义和初始化指针变量的定义和初始化 1.定义格式:定义格式:数据类型数据类型 *指针变量名指针变量名 【=变量地址变量地址】;例:例:int a10,*p1=a;/*数组名即地址数组名即地址*/char ch,*p2=&ch;/&-取地址运算符取地址运算符float x10,*p3=x;char str100,*p4=str;2.指针运算符指针运算符-*作用:作用:(在声明语句中在声明语句中)定义指针变量;定义指针变量;(在执行语句中在执行语句中)表示读写内存数据;表示读写内存数
6、据;例:例:int i,a10,*p=a;/在声明语句中定义指针变量在声明语句中定义指针变量p for(i=0;i*p+;/在执行语句中表示读写内存数据在执行语句中表示读写内存数据 while(-i=0)cout*(-p)*q j;3.通过指针变量引用它所指向的变量通过指针变量引用它所指向的变量例:例:int i=1,j=2,k,*p=&i;k=*p+j;三三.取地址运算符与指针运算符取地址运算符与指针运算符1.&-取运算对象的地址;取运算对象的地址;格式:格式:int a,b10,*p1,*p2;p1=&a;p2=&b1;9/26/2024102.*-用于访问地址对应的存储单元用于访问地址对
7、应的存储单元(指针所指向的变量或数组元素)(指针所指向的变量或数组元素)例例1:char str30=“Beijing2008”,*p=str;while(*p)cout*p+;例例2:char str30=“Beijing2008”,*p=str;for(p=str+7;*p!=0;p+)cout*p;【注注】&的运算对象必须是已定义过的变量或数组元素,但不可以的运算对象必须是已定义过的变量或数组元素,但不可以 是数组名。是数组名。*指针运算符的运算对象必须是地址,不能是整数,也不能指针运算符的运算对象必须是地址,不能是整数,也不能 是非地址型的变量。是非地址型的变量。&和和*优先级相同,优
8、先级相同,自右向左自右向左的结合性。的结合性。例例3:float a,*pa=&a;*&a -代表变量代表变量 a;&*a -错误,错误,因为因为 a 不是地址。不是地址。9/26/202411一一.指针的类型指针的类型1.指针的类型即声明指针时的数据类型指针的类型即声明指针时的数据类型指针声明格式:指针声明格式:数据类型数据类型 *指针变量名指针变量名 【=变量地址变量地址】;例:例:int a,*p1=&a;/*a不是地址,所以必须加不是地址,所以必须加&运算符运算符*/float s5,*p2=s;/*s 是地址是地址*/p2=&s1;/*s1 不是地址不是地址,所以必须加,所以必须加&
9、运算符运算符*/2.指针的类型决定了指针在内存空间移动的位置大小指针的类型决定了指针在内存空间移动的位置大小例:若例:若 char *p;则则 p+;移动移动 1个字节个字节;例:若例:若 int *p;则则 p+;移动移动 2个字节个字节(C)或或 4个字节个字节(C+);例:若例:若 float *p;则则 p+;移动移动 4个字节个字节;6.1.26.1.2 指针类型及指针运算指针类型及指针运算 9/26/202412二二.指针变量的运算指针变量的运算(1)指针变量和整数的运算指针变量和整数的运算 指针变量指针变量+整数整数 n -相当于指针向后移动了相当于指针向后移动了n个数据的位置个
10、数据的位置 指针变量指针变量-整数整数 n -相当于指针向前移动了相当于指针向前移动了n个数据的位置个数据的位置 指针变量指针变量+-先用指针的值,然后向后移动了先用指针的值,然后向后移动了 1 个数据的位置个数据的位置 指针变量指针变量-先用指针的值,然后向前移动了先用指针的值,然后向前移动了 1 个数据的位置个数据的位置 +指针变量指针变量-指针向后移动了指针向后移动了 1 个数据的位置个数据的位置 -指针变量指针变量 -指针向前移动了指针向前移动了 1 个数据的位置个数据的位置(2)指针变量和指针变量的减法运算指针变量和指针变量的减法运算若若 p1 和和 p2 指向同一类型的数据,则指向
11、同一类型的数据,则 p2 p1 表示两个指针之间数据的个数表示两个指针之间数据的个数.【注注】两个指针变量不能进行加运算。两个指针变量不能进行加运算。(3)指针变量的关系运算指针变量的关系运算-同类型指针可以进行关系运算同类型指针可以进行关系运算.格式:格式:指针变量指针变量1 关系运算符关系运算符 指针变量指针变量2 9/26/202413三三.指针变量的使用指针变量的使用1.给指针变量赋值给指针变量赋值格式:格式:指针变量指针变量=地址表达式;地址表达式;例:例:int a,*p1=&a;/*a表示地址,所以必须加表示地址,所以必须加&运算符运算符*/float s5,*p2=s;/*s
12、是地址是地址*/p2=&s1;/*s1 不是地址不是地址,所以必须加,所以必须加&运算符运算符*/2.引用所指向的变量引用所指向的变量引用格式:引用格式:*指针变量指针变量 (或或 *数组名数组名)例:设例:设 int a10,*p=a;数组元素数组元素 a4 的正确引用是的正确引用是 ()A.*(p+4)B.P+4 C.*p+4 D.a+4例例2:设设 int a10=1,2,3,4,5,6,7,8,9,10,*p=a;则不能表示数组则不能表示数组 a 中中 元素的是元素的是()A.*p B.A10 C.*a D.Ap-a例例3:设设 char a20=“Awitch”,*p=a;则则*(p
13、+2)的值是的值是 。9/26/2024141.new 和和delete 操作符操作符(1)new-动态内存分配操作符动态内存分配操作符.格式:格式:指针变量名指针变量名=new 类型名类型名长度长度;指针变量名指针变量名=new 类型名类型名长度长度长度长度;/申请动态多维数组申请动态多维数组功能:功能:new自动计算分配空间的大小;自动计算分配空间的大小;自动返回分配空间的首地址,赋予指针;自动返回分配空间的首地址,赋予指针;可以对分配的对象进行初始化可以对分配的对象进行初始化.【例例】double*p;p=new double3;/为指针为指针p分配分配3个个double型长度的空间型长
14、度的空间(2)delete-用于释放为指针分配的存储空间用于释放为指针分配的存储空间.格式:格式:delete 指针名;指针名;delete 指针名;指针名;/释放动态数组空间释放动态数组空间 6.1.3 自己给指针分配地址自己给指针分配地址 9/26/202415【例例5-3】使用使用new和和delete的例子的例子#includeusing namespace std;void main()/演示演示new 和和delete 的用法的用法double*p;p=new double3;/申请分配空间申请分配空间for(int i=0;i*(p+i);for(int i=0;i3;i+)co
15、ut*(p+i);delete p;/释放分配空间释放分配空间 9/26/202416一一.什么是引用什么是引用?1.引用引用-引用是变量或对象的别名。引用是变量或对象的别名。2.引用的声明引用的声明-引用通过运算符引用通过运算符&来定义来定义 数据类型数据类型&引用名引用名(别名别名)=变量名变量名;【例例】int x=56;int&a=x;/引用必须在声明的时候就完成初始化引用必须在声明的时候就完成初始化二二.引用的使用引用的使用 使用规则使用规则 引用不能独立存在,它只是其它变量的别名;引用不能独立存在,它只是其它变量的别名;引用必须在声明的同时就初始化;引用必须在声明的同时就初始化;引
16、用一旦定义引用关系就不可更改;引用一旦定义引用关系就不可更改;引用的使用和变量的使用相同;引用的使用和变量的使用相同;不能直接声明对数组的引用。不能直接声明对数组的引用。6.26.2 引引 用用 9/26/202417【例例5-4】引用示例引用示例#include using namespace std;void main()/演示引用的例子演示引用的例子int x=56;int&a=x;/a是是x的引用的引用int&r=a;/r是是a的引用,三者同指向一个内存单元的引用,三者同指向一个内存单元coutx=x,&x=&x,a=a,&a=&a,r=r,&r=&rendl;r=25;/引用引用r改
17、变值,使得改变值,使得x和和a同时改变同时改变.coutx=x,&x=&x,a=a,&a=&a,r=r,&r=&rendl;运行结果:运行结果:x=56,&x=0012FF7C,a=56,&a=0012FF7C,r=56,&r=0012FF7Cx=25,&x=0012FF7C,a=25,&a=0012FF7C,r=25,&r=0012FF7C9/26/202418【例例5-5】指针引用的示例指针引用的示例#includeusing namespace std;void main()/演示引用的例子演示引用的例子int x=56,*p1=&x;int&a=x;/引用引用xint*&p2=p1;/
18、引用引用指针指针p1coutx=x,a=aendl;*p2=65;cout*p1=*p1,*p2=*p2endl;int*p3=&a;*p3=32;coutx=x,*p1=*p1 endl;输出输出结果:结果:x=56,a=56 *p1=65,*p2=65 x=32,*p1=329/26/202419三三.引用的主要用途引用的主要用途 1.通过引用传递函数参数通过引用传递函数参数-实现地址传递,改变实参的值实现地址传递,改变实参的值.【例例】#includeusing namespace std;void swap(int&x,int&y)/用引用作为形参,传递地址用引用作为形参,传递地址 i
19、nt j;j=x;x=y;y=j;void main()int a=12345,b=54321;cout“函数调用前函数调用前 a=”a“,b=”bendl;swap(a,b);/通过引用,返回实参的值通过引用,返回实参的值cout“函数调用后函数调用后 a=”a“,b=”bendl;运行结果:函数调用前运行结果:函数调用前 a=12345,b=54321 函数调用后函数调用后 a=54321,b=12345 9/26/2024202.用引用作为函数的返回值用引用作为函数的返回值 用法用法:(1)返回引用的函数需加以说明,格式为:返回引用的函数需加以说明,格式为:&函数名函数名(形式参数形式参
20、数);(2)返回引用的语句是:返回引用的语句是:return 变量名;变量名;【例例】#includeusing namespace std;int&fun(int&pf);/返回引用函数声明返回引用函数声明void main()int pa=10,pb;cout“输出输出1:pb=”(pb=fun(pa)endl;int&pc=fun(pa);/使用引用返回的地址使用引用返回的地址cout“输出输出2:pc=”pcendl;cout“输出输出3:”+fun(pa)endl;/返回的引用可以继续操作返回的引用可以继续操作int&fun(int&pf)pf=pf+10;coutpfendl;re
21、turn pf;9/26/202421 引用变量的说明:引用变量的说明:类型名类型名&引用变量名引用变量名 =变量名变量名;引用表示被引用变量的别名引用表示被引用变量的别名。引用调用引用调用-引用变量作为函数的形参引用变量作为函数的形参 p.1619/26/202422.9/26/2024235.5.1 数组使用错误数组使用错误1.数组越界数组越界 【例例】int num100;for(int x=1;x=100;x+)numx=x;/num100越界越界2.字符串长度越界字符串长度越界 【例例】char str5;str=“abcde”;说明:以上有说明:以上有 2个错误:个错误:字符串含结
22、束标志字符串含结束标志 0,赋值字符串长度赋值字符串长度=size-1.不能向字符串名不能向字符串名(地址常量地址常量)直接赋值,正确赋值方式为:直接赋值,正确赋值方式为:char str5=“abcd”;或或 strcpy(str,“abcd”);6.5 使用数组与指针易犯的错误使用数组与指针易犯的错误 9/26/2024245.5.2 指针使用不当指针使用不当1.使用没有初始化的指针使用没有初始化的指针【例例5-12】#includeusing namespace std;void main()int x,*p1;x=25;*p1=x;/使用了没有初始化地址的指针,使用了没有初始化地址的指
23、针,应先加上应先加上 p1=&x;【例例5-13】#includeusing namespace std;void main()char *a;strcpy(a,“DATA”);/使用了没有初始化地址的指针使用了没有初始化地址的指针 strcpy(a,“DATA”);应改为:应改为:a=“DATA”;9/26/2024252.指针用法不对指针用法不对【例例5-15】#includeusing namespace std;void main()int x,*p1;x=25;p1=x;/为指针赋值必须是地址为指针赋值必须是地址 应改为应改为 p1=&x;#includeusing namespac
24、e std;void main()char s100,*p1;p1=&s;/s本身就是地址本身就是地址 应改为应改为 p1=s;9/26/2024263.对指针运算理解不对对指针运算理解不对#includeusing namespace std;void main()int i;int*s1,*s2;if(s1=new int10)=NULL)cout“Out of memory”endl;exit(1);s2=s1;for(i=0;i10;i+)*s1+=i;cout“两指针之间的元素个数是:两指针之间的元素个数是:”(-s1 s2+1)/sizeof(int)endl;/两指针相减即两指针
25、间的数据个数两指针相减即两指针间的数据个数.delete s2;9/26/2024274.使用无效的指针使用无效的指针【例例5-7】#includeusing namespace std;void main()char *p;p=new char100;/p有可能获得一个空有可能获得一个空(NULL)指针指针gets(P);coutpendl;应在应在 p=new char100;后面后面加入对加入对new操作的有效性检查:操作的有效性检查:if(p=NULL)cout“out of memory”endl;exit(1);.9/26/202428.9/26/202429.9/26/202430.9/26/202431.9/26/202432.9/26/202433.9/26/202434.9/26/202435.9/26/202436.9/26/202437.9/26/202438 9/26/202439 如何上大学?9/26/202440