C高级语言程序设计第6章.ppt_第1页
C高级语言程序设计第6章.ppt_第2页
C高级语言程序设计第6章.ppt_第3页
C高级语言程序设计第6章.ppt_第4页
C高级语言程序设计第6章.ppt_第5页
已阅读5页,还剩82页未读 继续免费阅读

下载本文档

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

文档简介

*1 C+高级语言程序设计 第6章 指针和引用 北京邮电大学 信息与通信工程学院 北京邮电大学信息与通信工程学院 指针(Pointer)是C+和C的一 种数据类型。很多其他高级语言 也有类似的数据类型。引用( Reference)则是C+所特有的一 种数据类型。指针和引用在概念 上和使用上都有相似之处,但是 也有重要的差别。 * -2-北京邮电大学信息与通信工程学院 第六章 指针和引用 6.1 指针的概念 6.2 指针的运算 6.3 指针访问动态内存 6.4 指向结构体的指针 6.5 引用概念 6.6 指针和引用作为函数的参数 6.7 指针和引用作为函数的返回值 6.8 指针和字符串 6.9 通过指针访问数组 * -3-北京邮电大学信息与通信工程学院 6.1 指针的概念 *4北京邮电大学信息与通信工程学院 * 北京邮电大学信息与通信工程学院-5- 6.1.1 指针和指针变量 指针是变量的地址。或者说是在内存中,存放 某种类型变量的地址。 例如,定义了整型变量a,a的地址就是一个指 针。 也可以不定义任何变量,只是指定内存某个地 址开始(如0x00430100)的4个字节存放整型 变量,这样的地址也是指针。 存放指针的变量就是指针变量。 * 北京邮电大学信息与通信工程学院-6- 6.1.1 指针和指针变量 当声明了一个指针变量后,确定了三件事: n变量本身在内存中所分配的地址和字节数,指针变 量总是占有4个字节; n系统允许的地址范围,以及地址单元内可以存放的 内容; n指针变量可以进行的运算。 访问指针变量时,只能看到地址。只有通过这 个地址,才能访问地址单元中的内容。这样的 访问称为对于内存单元的间接访问。 * 北京邮电大学信息与通信工程学院-7- 6.1.2 指针变量的声明和初始化 指针变量声明的格式是: *变量名1, *变量名2; 例如: int *va1, *va2; char *ch1, *ch2; 指针变量在声明后,变量的值(地址)是随机 的。这样的指针变量是不能安全的使用的。因 为其中的随机地址完全可能不是有效的数据地 址。 * 北京邮电大学信息与通信工程学院-8- 6.1.2 指针变量的声明和初始化 在声明指针变量时的“*”,有两个含义: n声明变量va1、va2、ch1、ch2都是指针变量; n说明变量va1和va2的类型是(int *)型,即指向 整型变量的指针。va1和va2所指定的地址单元中, 只能存放整型数据。类似地,ch1和ch2的类型是( char *)型,它们所指定的地址单元中,只能存放 字符。 指针变量都是有类型的.指针变量的类型就是 它所指定的地址单元中存放的数据的类型。 * 北京邮电大学信息与通信工程学院-9- 6.1.2 指针变量的声明和初始化 指针变量的初始化有两种方法:在声明时的初 始化和声明后的初始化。 声明指针变量时就进行初始化的格式是: *指针变量名= n其中的变量名应该是已经声明或定义的同类型变量 名。例如: nchar ch1=Y, ch2=A; nchar *pch1= * 北京邮电大学信息与通信工程学院-10- 6.1.2 指针变量的声明和初始化 也可以在声明指针变量后,用赋值的方式对它 们进行初始化。例如: nint i1=Y, i2=A; nint *pi1, *pi2; npi1= npi2= 没有初始化指针变量是不可以使用的。编译带 有这样的指针变量的程序,编译系统会给出警 告,而运行时会出现错误。 6.2 指针的运算 * -11-北京邮电大学信息与通信工程学院 6.2 指针的运算 表6.1 指针的运算 * -12-北京邮电大学信息与通信工程学院 * 北京邮电大学信息与通信工程学院-13- 6.2.1 指针的赋值运算 指针的赋值运算一定是地址的赋值。用来对指针变量 赋值的可以是: n同类型变量的地址; n同类型的已经初始化的指针变量; n其他同类型的指针。 此外,也可以用0或者NULL对指针变量赋值。使得变量 包含的是“空指针”,即不指向任何的内存物理地址。 必须注意:不同类型的指针是不可以互相赋值的。在 指针赋值时,不存在类型自动转换的机制。 * 北京邮电大学信息与通信工程学院-14- 例6.1 观察以下指针赋值运算的结果。如果将注释去 掉,结果将如何? #include using namespace std; void main() int va1=100,*pva1; float vf1=A,*pvf1,*pvf2; int *pva2=NULL; cout using namespace std; void main() char ch1=a,*ch; int k1=100; ch= /指针ch指向变量ch1 cout using namespace std; void main() int va=100,*pva,*ppva; /ppva是指向指针的指针 int k1=100; pva= cout using namespace std; void main() int k110=11,24,37,44,58,66,79,86,93,108,*k; k= for(int i=0;i; void类型的指针变量中存放的也是内存的地址 ,但是不指定这个地址单元内的数据的类型。 * 北京邮电大学信息与通信工程学院-24- 6.2.5 void类型指针 void类型的指针的使用: n任何其他类型的指针都可以赋值给void指针。必须 注意,这样赋值后的void指针的类型仍然是void。 nvoid类型指针不可以直接赋值给任何其他类型的指 针。 n无论何时,void指针都不可以通过间接引用来访问 内存中的数据。 n要通过void类型指针访问内存的数据,必须进行指 针类型的强制转换,才可以通过指针间接引用访问 内存数据。 * 北京邮电大学信息与通信工程学院-25- void类型指针 void类型指针还有一个具体的应用:显示字符 指针的内容。除了字符指针外,其他指针都可 以直接用cout语句来输出地址值。但是,用 cout输出字符指针时,则是输出它所指向的字 符串。可以将字符指针强制转换为void指针, 再用cout语句输出,就可以看到地址值。如: char *pch=“Hello C+“; cout using namespace std; #include void main() char src10=“012345678“; char dest10; char* pc=(char*)memcpy(dest,src,10); cout (p); 在编译时有语法错误:“不能将double*转换为 char*”,也就是说指针的强制类型转换也是不允许的 。 但是,如果使用C风格的类型转换:pch=(char*)p;在 编译时没有语法错误,仅在执行时有问题。 所以,还是要使用static_cast来进行强制类型转换。 唯一允许的是void指针和其它指针类型之间的转换 * 北京邮电大学信息与通信工程学院-29- /例6-5利用格式控制符hex可以显示整数的机器数的程序 #include using namespace std; void main() float f=1.0; float* fPtr= /浮点指针 void* fv= int* iPtr=static_cast(fv); /浮点变量地址赋给整型指针 cout “ “ (初值) n运算的结果:如果申请成功,返回指定类型内存的 地址;如果申请失败,返回NULL指针。 动态内存使用完毕后,要用delete运算来释放 。delete运算符使用格式: delete ; * 北京邮电大学信息与通信工程学院-33- 6.3.2 动态数组空间的申请和释放 申请动态一维数组时,要在new表达式中加上 申请数组的大小: new 常量表达式 ; n注意:在动态申请数组空间时,不可以对数组进行 初始化。 n也可以申请二维数组的空间: int (*pi_marray)4; pi_marray = new int34; 释放动态数组空间都用相同的表达式: delete ; * 北京邮电大学信息与通信工程学院-34- 6.3.3 内存泄漏和指针悬挂 内存泄漏是指动态申请的内存空间,没有正常 释放,但是也不能继续使用的情况。如: char *ch1; ch1 = new char(A); char *ch2 = new char; ch1=ch2; n原来为ch1所申请的存放字符A的空间就不可能再使 用了,产生了内存泄漏。 * 北京邮电大学信息与通信工程学院-35- 6.3.3 内存泄漏和指针悬挂 让指针指向一个已经释放的空间,即所谓的指 针悬挂(Dangling)。如: char *ch1, *ch2; ch1 = new char; ch2 = ch1; *ch2 = B; delete ch1; n指针ch2就是指向了一个已经释放的地址空间,形成 指针悬挂。如果还要用delete ch2;语句来释放ch2 所指向的空间,就会出现运行错误。 6.4 指向结构体的指针 * -36-北京邮电大学信息与通信工程学院 指向结构体的指针 定义变量时,我们可以定义指向int型的指针 变量,类似的,可以有指向新定义的结构型数 据类型的指针变量。 声明了指向结构的指针后,必须对指针初始化 。现在我们知道对于指针的初始化有两种方法 :其一是用已经定义的变量地址来初始化,其 二是用new申请一个地址来对指针赋值。 * -37-北京邮电大学信息与通信工程学院 * 北京邮电大学信息与通信工程学院-38- 具体对结构指针来说: (1)可以将结构变量的地址赋给结构指针,使用取地址“/学号 char name20; /姓名 float score;/成绩 ; student stu=20041118,“Li Li“,F,18; /定义结构变量并初始化 student * ps= /定义结构指针并初始化 * 北京邮电大学信息与通信工程学院-39- (2)使用new操作在堆中给结构指针分配空间。 例如: student * ps=new student; /定义结构指针用动态地址初始化 用结构指针访问结构成员时,用箭头操作符代替 原来的点操作符对结构体成员进行操作。比如,把 学生的成绩输出显示,语句如下: coutscore; 其中,ps-score等价于(*ps).score。 * 北京邮电大学信息与通信工程学院-40- 解:说明:每个员工的信息包括姓名、工作证号、薪水,定义 为结构类型。定义结构指针并让它的指向确定,通过结构指 针访问结构成员,输出显示员工的信息。 /例6-6 结构指针的定义和使用 #include #include using namespace std; struct Employee char name20; unsigned long id; float salary; ; 例6-6 结构指针的定义和使用。 * 北京邮电大学信息与通信工程学院-41- void main() Employee pr1; Employee* prPtr; prPtr= strcpy(prPtr-name,“zhang san“); prPtr-id=98001; prPtr-salary=3350.0; cout name id salary 其中的变量名必须是已经定义的,并且和引用的 类型必须相同。例如: int someInt; int 必须注意:引用必须在声明的时候就完成初始化 ,不可以先声明引用,然后再用另一个语句对它 初始化。 * 北京邮电大学信息与通信工程学院-45- 引用有以下的特点: n引用不能独立存在,它只是其他变量的别名; n引用必须在声明的同时就初始化; n引用一旦定义,引用关系就不可以更改,即B若 是A的引用,就不可能是其他变量的引用; n引用的类型就是相关的变量的类型,引用的使用 和变量的使用相同。 * 北京邮电大学信息与通信工程学院-46- 例6-7 引用的使用。观察以下程序的结果。 #include using namespace std; void main() int intA=10; int cout using namespace std; void Swap(int *a, int *b); void main() int x(5), y(10); cout using namespace std; void swap_1(int j=x; x=y; y=j; void main() int a=12345, b=54321; cout *; n例如: const int *ptint; n指针ptint的类型是(const int *),也就是指向一 个恒定的整型数。 * 北京邮电大学信息与通信工程学院-58- 例6.10 常指针示例。观察以下程序的运行。 #include using namespace std; void main() int ia=10, ib=20; const int *ptint; ptint=/用ia地址初始化 cout using namespace std; void Move(int *a); void main() int x5=10,20,30,40,50, *px=x; cout using namespace std; void Move(int *a); void main() int x5=10,20,30,40,50, *px=x; cout using namespace std; int * reverse(int const * list, const int size)/指针函数 int result6;/函 数中定义的局部数组 for (int i = 0, j = size - 1; i using namespace std; int * reverse(int const * list, const int size)/指针函数 int *result = new intsize; /函数中定义的动态数组 for (int i = 0, j = size - 1; i n返回引用实际是返回地址。在使用上,或者直接使 用这个地址;或者使用这个地址单元的数据。 n返回的引用可以作为左值继续操作,而返回的变量 值是不可以继续运算的。这是返回引用和返回变量 值在使用上的主要区别。 * /例6-17 引用作为函数的返回值 #include #include using namespace std; struct person char name15; int contribution; double bonus; ;/定义结构体 person p1=“Li Li“,500,0,p2=“Zhao Zhao“,600,0;/两 名职工是全局变量 person else return p2; * 例6.17引用作为函数返回值。 void main() compare().bonus=1000; /返回值作为左值直接操作 cout #include using namespace std; void main() int n; char *array1 = “Happy Birthday to You“; char array3 15 ; char array2 25 ; strcpy( array2, array1 ); cout using namespace std; void main() char ChArray=“This is a string.“,*ptch; int i,j,k,offset1,offset2; ptch=ChArray;/指针初始化 for(i=0;ChArrayi!=0;i+); cout using namespace std; void main() int intArray10=8,11,23,34,45,56,65,78,86,97,*ptint; int i,num,sum; float average; ptint=intArray; sum=0; num=sizeof(intArray)/sizeof(*intArray); for(i=0;i *常量表达式; n例如: char *member_name10; 注意和声明指向一维数组指针的差别: char (*member_pointer)10; * -82-北京邮电大学信息与通信工程学院 指针数组 指向字符的指针: char *member_name=“Merry“,“John“,“Hill“; 指向这样的指针数组的指针: char *arr=member_name;

温馨提示

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

评论

0/150

提交评论