第2章 指针和引用.doc_第1页
第2章 指针和引用.doc_第2页
第2章 指针和引用.doc_第3页
第2章 指针和引用.doc_第4页
第2章 指针和引用.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

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

文档简介

第二章 指针和引用在C/C+入门教材中,指针和引用一般放在稍后篇幅。本课放在前面,因为指针和引用与C/C+一些较高级的问题关系密切。一、 指针的概念和声明1指针是一种数据类型 指针是一种数据类型,指针所存放的是某个变量(或常量)的地址,指针可以指向任何类型的变量(或常量)-通常把这称为指针的类型,但指针本身永远是unsigned long int类型的。 比如:int *p1; float *p2; char *p3,分别指向不同的类型,但指针本身是unsigned long int类型的,其具体的长度应等于CPU寻址能力。2指针的声明 指针的用法很多,可以指向常量、变量、数组、函数、对象。指针的声明有一条不成文的规则: 定义一个指针 *最好靠近要定义的标识符旁边。如 char *p; /这说明 p 是指向字符类型的指针,但 char* p; /也是可以的,但没有上一种定义这么直观, 但在读别人的代码时,常有这种写法。常常不容易看懂别人写的指针声明,有人提出“从右到左”解释指针声明的办法,指针“*”读做“指向”,试一试:int *p1; /p1指向 整型变量。int* p1; /与上面写法等效float *p1;/ p1指向 浮点型变量。float* p1;/与上面写法等效插入小问题:constint a=1和 int const a=1有区别吗? 下面几个有关const和指针声明的问题是就业考试常见的:const int *a;/ a指向 整型,该整型是常量/指针a不是常量,a指向的是整型常量const int* a;/同上 int const *a;/同上。int const和const int的const都修饰intint* const a;/ a是常量,指向 整型/换句话说,a是指针常量。const* int a;/?const int* const a / a是常量.指向整型.常量/换句话说,指针a和它所指的都是常量。上面几个有关const 的问题虽有特殊性,但也符合“从右到左”解释指针声明的原则的。int *p4 /数组p是(元素是)指向整型的指针。 /这是指针数组 int* p4 /同上int (*p)4 /(先从右到左读括号内的)P指向, /(先从右到左读括号外的)指向数组,数组元素类型为int, /这是指向数组(首元素)的指针int *p /指向另一个指针.(另一个指针)指向一个整型 int *(*)p /同上。注意*运算符结合性是“从右到左”的。int (*)*p /?int (*p)() / p是指针,指向一个返回类型为int的函数入口地址 /这是指向函数的指针int *a( ) /函数a返回指针,该指针是int型的 /这是返回类型为指针的函数int* a( )/同上 int* a(int,int) /同上二、指针的赋值和运算1基本问题int a=10; int *p; p=&a; /这是最常见的形式上机习题1:int a; int *p; p=&a; a已定义但无初值会怎么样?为什么?/下面的代码结果是什么?注意 * & 算符是右结合的int a=10; int *p; p=&a;p=& *p; /p是a的地址, *p就是a*p=20; /更改了a上机习题2:数组的本质是指针, 实际上是变址算符, 用指针进行+或-运算遍历数组比用下标遍历数组效率高, 试分别定义int, short int, char, float类型的数组,用+或-算符遍历数组. 每次+或-,显示数组元素, 并显示指针移动了几个字节?上机习题3:分别定义int, short int, char, folat等类型的指针P, 求出指针P占用的字节数和指向的变量地址。每次启动该程序,在变量不变的前提下,P指向的地址是否都有变化?结合“操作系统”课程关于内存管理的学习,分析C/C+的指针,在程序员不强加干预时,指向的是绝对地址还是进程的相对地址?如程序员强加干预(比如令p=1000),指向的是绝对地址还是进程的相对地址?上机习题4:有人说“字符串的本质是char数组”,试设计一个小程序验证之。2指向函数的指针int (*p)() ;/ p是指向函数的指针,p指向函数的入口地址。/假如有一个函数 int max(.),和变量int c则p=max ;/将max的入口地址给p。不能写为p=max(),因为max()返回类型不是pc=(*p)();/调用max,可“自右向左”读为:将p指向的.函数.赋值给c。/ (*p)就是max();而p=max只表明将p指向 max的入口地址。c=*p();/这样写变成什么了?“自右向左”读为:调用函数p(.),将返回值所指向的?/赋值给c。很显然是错的,因为要调用的是max(),而不是不存在的p函数。指向函数的指针有什么用处?一般的教学举例中,单指向一两个函数没什么用处。但在实际编程中,可以用一个指针来灵活地代表一组函数中的任一个,有些类似面向对象的“多态性”。有些高端的C程序用到这一点。“指向函数的指针”和“返回类型为指针的函数”在C/C+的各种库,以及专业的原代码中,是常见的,新手不太容易适应。所幸的是,上述库或原码的指针标识符一般都以p打头。三、空指针、空指针常量、NULL 和 01什么是Void指针类型?C语言新标准允许定义一个指针变量,但不指定它指向哪种数据类型,比如: char *p1; void *p2; p1=(char *)p2; /类型强制(显式)转换 p2=(void *)p1; /类型强制(显式)转换很常用的是将一个函数定义为void *类型,比如: void *fun(.) /fun返回一个“空类型”的地址,/如需要引用此地址,要进行显示类型转换,比如: char *p1; p1=(char *)fun()2什么是空指针常量(null pointer constant)?值为0的整数常量,或返回为void *的表达式,叫空指针常量。比如0, 4-4, (void*)0 。但C+不推荐Void指针类型,所以通常选 0 作为空指针常量,而不选择 (void*)0。3什么是空指针(null pointer)? 如果 p 是一个指针变量,则 p = 0;p = 4 - 4;(对于 C 来说还可以是 p = (void*)0;)等“赋值为空指针常量”的操作, 都将使p成为一个空指针,系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。4什么是 NULL?是C/C+中的对空制针常量的宏定义,定义在 (或其它头文件,一般把NULL定为0),因此,可以用 p = NULL。要注意的是:NULL是一个“为空”的概念,0是其实现。5空指针(null pointer)指向了内存的什么地方?表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址(绝对0地址或进程的0地址);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针。在实际编程中不需要了解在我们的系统上空指针到底是一个,我们只需要了解一个指针是否是空指针就可以了编译器会自动实现其中的转换。注意:不要把空指针的内部表示等同于整数 0 的对象表示如上所述,它们是不同的。因为空指针概念实现为0地址(绝对0地址或进程的0地址),而不是整数0。6如何判断一个指针是否是一个空指针?if ( p = 0 );if ( 0 = p ); if ( p = 3 - 3 ); if ( p = NULL );if ( NULL = p )/推荐使用最后两种的NULL比较法,前两种不敢保证在所有编译器都能通过,虽然它们在概念上“似乎”是正确的。对于空指针值,一般的文档(比如 man)中倾向于用 NULL 表示,而没有直接说成 0。7malloc 函数在分配内存失败时返回 0 还是 NULL?malloc 函数是标准 C 规定的库函数。在标准中明确规定了在其内存分配失败时返回的是一个 “null pointer”(空指针) 小结:通过对空指针等概念的讨论,我们看到C语言的定义及实现有个别不完善和不通一的地方,但以良好的编程习惯,比如用if ( p = NULL )因为NULL在头文件明确定义了,而不用if ( p =0 ),可以避开这些问题。四、引用引用是C+特有的。先回顾一下以前学过的两个知识点:Q1:C语言中指针作为函数的参数有什么效果?Q2:JAVA中对象的引用赋值?1C+引用的基本性质引用(reference)是被引用对象的一个别名,它与被引用对象是一个对象。定义引用的表示方法与定义指针相似,只是用&代替了*。例如: int pt1=0;int &pt2=pt1; /定义了pt2为pt1的引用。 /pt1和pt2表示同一对象。有些引用的声明也很复杂,看懂这些声明用与指针相同的“从右向左”原则即可。需要特别强调的是引用并不产生对象的副本,仅仅是对象的别明同义词。因此,当下面的语句执行后:pt2=10;/pt1和pt2都为10。引用必须在定义时马上被初始化,因为它必须是某个东西的别名。你不能先定义一个引用后才初始化它(这是引用与指针的区别之一)。例如下面语句是非法的:int &pt3;pt3=pt1;2C+引用的用途那么既然引用只是某个东西的别名,它有什么用途呢?下面讨论引用的两个主要用途:作为函数参数以及从函数中返回左值。 1)传递可变参数传统的c中,函数在调用时参数是通过值(实参的拷贝)来传递的,这就是说函数的参数不具备返回值的能力,因此不能修改实参。所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。比如,实现两整数变量值交换的c程序如下:void swapint(int *a,int *b)int temp;temp=*a;a=*b;*b=temp;使用引用机制后,以上程序的c+版本为:void swapint(int &a,int &b)int temp;temp=a;a=b;b=temp;调用该函数的c+方法为:swapint(x,y); c+自动把x,y的地址作为参数传递给swapint函数。引用可以给函数传递大型对象,当大型对象被传递给函数时,使用引用参数可使参数传递效率得到提高,因为引用并不产生对象的副本,也就是参数传递时,对象无须复制。2)引用返回左值(赋值算符左面的表达式)如果一个函数返回了引用,那么该函数的调用也可以被赋值。这里有一函数,它拥有两个引用参数并返回一个双精度数的引用:double &max(double &d1,double &d2)return d1d2?d1:d2;由于max()函数返回一个对双精度数的引用,那么我们就可以用max() 来对其中较大的双精度数加1:max(x,y)+=1.0;3引用和指针的关系粗看起来,引用是指针的改头换面,或许在编译器的实现上是这样,但两者概念有明显区别:1)创建指针是创建一个新对象,创建引用不是.在语法上的区别是:1)声明引用时必需同时初始化,因此引用总是有确定的被引用对象,使用引用是安全的. 引用必须被初始化,指针不必。2) 引用初始化以后不能被改变,指针可以改变所指的对象。3) 不存在指向空值的引用,但是存在指向空值的指针。int mian()int i=5;int& j=i;/j是i的别名,不是新对象int* p=&i;/p是新对象j=0; /改变了ip=0; /只改变p,i没变问题:下面的引用声明,哪个有意义,哪个没有(从右到左读)int& const x= ; /const是多余的const int& x= ; / 有意义,x引用了一个整型常量 const int& const x= ; / 右面的const是多余的课后习题:1 char *p; 和 char* p; 的指针声明是等效的吗?2 按“从右到左”原则,解释以下有关指针的声明:const int *a; const int* a; int const *a;int* const

温馨提示

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

最新文档

评论

0/150

提交评论