C++程序设计语言(李雁妮) 第5章

上传人:E**** 文档编号:89345223 上传时间:2019-05-23 格式:PPT 页数:117 大小:921.50KB
返回 下载 相关 举报
C++程序设计语言(李雁妮) 第5章_第1页
第1页 / 共117页
C++程序设计语言(李雁妮) 第5章_第2页
第2页 / 共117页
C++程序设计语言(李雁妮) 第5章_第3页
第3页 / 共117页
C++程序设计语言(李雁妮) 第5章_第4页
第4页 / 共117页
C++程序设计语言(李雁妮) 第5章_第5页
第5页 / 共117页
点击查看更多>>
资源描述

《C++程序设计语言(李雁妮) 第5章》由会员分享,可在线阅读,更多相关《C++程序设计语言(李雁妮) 第5章(117页珍藏版)》请在金锄头文库上搜索。

1、第5章 指针、数组和结构,5.1 指针 5.2 数组 5.3 指向数组的指针 5.4 指向函数的指针 5.5 指向void*的指针 5.6 常量 5.7 引用 5.8 结构 小结 练习题,5.1 指 针 5.1.1 指针与指针变量 所谓指针,即一个变量的内存存储地址。假设变量v的地址是0x06AF(十六进制),我们就说v的指针(或称指针值)是0x06AF。 对于类型T(T为基本类型或为自定义类型),指针类型(表示为T*)是“指向T类型对象的指针”,即一个T* 类型的指针变量只能存放一个类型为T的对象的地址。例如: char c=a;,图5.1 char*类型的变量pv中存放char类型变量c的

2、地址,char* pv= /取变量c的地址,并赋给指针char*类型的变量pv用图5.1表示如下。,引入指针类型的目的是用某个指针变量中的值间接地存/取它所指的对象的内容。 大部分教科书及专业书籍都把指针和指针变量统称为指针,因此,到底是指针还是指针变量,读者在学习与阅读时一定要注意其上下文环境,并根据上下文来进行判断。,5.1.2 为什么要使用指针变量 通常,我们是用某种类型的变量去存储相应类型的值,然后,通过变量名去存/取(注意:计算机的动作是在内存中存/取)其中的值。既然能用变量名(与某块内存绑定)直接存/取内存中的值,那么为什么还要用指针来间接存/取内存中所存储的值呢? 应用中,以下几

3、种情况必须使用指针: (1) 如果在起始地址为 Av的存储空间 Sv 中存储的值是在运行时根据运行情况才写入的,不能事先规定所写入的是哪个变量的值,能够保证的只是所写入的一定是类型为 T 的值,这时应该采用指针。例如,多进程之间利用一块共享内存进行通信时,其底层实现采用的就是指针,如图5.2所示。,图5.2 多进程之间的通信,(2) 如果需要同时对一组同类型的数据进行多个侧面或角度的组织,以有效地支持多种不同性质的操作(源数据要求不动),这时亦应该使用指针。例如,某应用欲实现一批整型数同时进行递增和递减排序,并要求源数据保持不动,这时就需要采用指针,如图5.3所示。,图5.3 源数据要求不动的

4、一批同类型数据的递增、递减排序,(3) 对于连续存储着类型为T的许多个值(例如数组)的情况,当需要依次进行某种处理时,可以在不需要知道数组下标(或数组的界)的情况下,用改变一个指针变量的值的方式来依次进行这一批同类型量的访问,如图5.4所示。 此外,指针还有其它的一些应用场合,此处不一一介绍。,图5.4 用指针对一批连续存放的同类型值的处理,5.1.3 指针变量的声明与定义 与指针相关的声明共分两类,即定义声明和非定义声明。 1定义声明 (1) 定义声明与数据相关的指针,例如: char* pc; /pc:指向char类型值的指针变量 int* pi; /pi:指向int类型值的指针变量 ch

5、ar* ppc; /ppc:指向“指向char类型值的指针”的 指针变量 int* ap15; /ap:由15个指向int类型值的指针变量 构成的指针数组,(2) 定义声明与函数相关的指针,例如: int (*fp)(char*); /fp:指向参数为char*类型、返回值为int类型的函数指针,2非定义声明 例如: int* f(char*); /参数为char*类型、返回值为int*类型 的函数声明 C+的语法并不限定多级指针的定义,例如我们可定义一个二级指针: char* ppc; 则ppc指针变量中就可存放指向char类型的指针变量的地址,如图5.5所示。,图5.5 二级指针变量中的内

6、容,我们亦可定义一个三级指针(或更多级的指针),例如: int* ppi; 但实际应用中,应避免定义复杂的多级指针,二级指针变量足矣!,5.1.4 指针变量的操作 设T为任意类型(基本类型或用户自定义类型),则T类型指针变量的类型为T*。与指针类型相关的操作如下。 1取地址 操作符: /取c变量的地址并赋给指针变量p,2求内容(内容解析) 操作符:*,一元前缀运算符,采用右结合律。 语义:以相应指针变量中的值为地址,求出该地址中存储的值并返回之。 例如: char c = a; char* p = 则*(&c)=c,&(*p)=p。,3指针变量的自增(减)操作 指针变量可进行前缀/后缀的自增(

7、减)操作。例如: char c=a; char* pc=,4指针变量的加(减)操作 指针变量可与一个整数常量进行加、减操作。设N为一整型常量,则 pt+N; /等价于pt=pt+N*sizeof(T) ptN; /等价于pt=ptN*sizeof(T) 5指向同一数组的指针变量的相减操作 当两个同类型的指针变量指向同一数组时,两指针变量可进行相减操作。相加操作没有定义,被认为是非法操作。例如: int a=1,2,3,4,5,6; int* pa1,pa2;,pa1=a; /pa1指向数组首元素a0 pa2= /错误!没有定义 由于指针变量的自增(减)操作、加(减)操作是直接针对内存地址的操作

8、,所以在进行这些操作时,一定要注意指针的越界问题。关于此问题的讨论与处理详见下文。 T*类型指针变量的取值范围为T类型变量的所有的合法地址。,5.1.5 常量零(0) 一般而言,数字字面值0的类型为整型。由于C+中允许各种基本类型的相互转换,因此,数字0广义地说,可作为任意整型、浮点型、指针、指向成员的指针变量的字面值常量。因此,在上述情况下,数学0的类型就与上下文环境相关,并由其上下文环境所决定。 因计算机内存地址为0的单元一直保留未用,即没有任何对象会被分配到内存地址为0的地方,故0可用作一个指针变量的字面值常量。当一个指针变量初始化为0时,表示它此刻没有指向任何对象。,在C中流行用宏NU

9、LL表示0。由于C+不同的实现可能对NULL的定义不同,所以,直接采用0而非NULL会使得指针的初始化更可靠、安全。如果你非常熟悉C,且习惯于采用C的宏NULL,建议在编写C+程序时可先定义: const int NULL=0; /定义NULL是一个表示0的字符常量 然后在程序中再采用符号常量NULL。,5.2 数 组 对于类型T,一个数组类型Tsize(size表示数组中元素的个数,一般为整型常量)是类型为T的size个元素的有序集合,数组中的元素可用下标访问,其下标范围为0size-1。 数组类型属于构造类型,即一个数组类型是由两个类型构造而成的:一个是数组元素的类型(如T类型),另一个是

10、索引(或称下标)类型(如0, 1, , size-1,即对应索引类型的值集)。标准C+规定:数组元素的类型可为任意数据类型(包括另一个数组类型,但必须保证其元素的类型是同质的),而索引(下标)类型要求其值集上的元素要有偏序(顺序)关系(一般为整型或枚举类型)。,5.2.1 数组的定义与初始化 在C+中,可定义一维数组和多维数组,定义方式如下例所示: int a10; /定义一个元素类型为int,元素个数为 10的一维整型数组a int b23; /定义一个元素类型为int,元素个数 (2行3列)为6的二维数组b 定义数组时,其数组类型和数组类型的变量(后者通常简称为数组)一般在定义声明中是同时

11、声明的。例: float v3; /float3 v;,char* a32; /(char*)32 a; int d2107; /(int10)7 d2; 上述第一条语句定义了一个元素类型为float,元素个数为3的数组类型,并定义了这种数组类型的一个变量为v,数组类型与其类型的变量二者在定义时同时声明。 第二条语句定义了一个元素类型为char*,元素个数为32的数组类型(即字符指针数组),并定义了该数组类型的一个变量a,数组类型与其类型的变量二者在定义时同时声明。,第三条语句定义了一个元素类型为int10(一维整型数组,元素个数为10),元素个数为7的数组类型(即数组中的数组),并定义了该数

12、组类型的变量d2,数组类型与其类型的变量d2二者在定义时同时声明。 一旦定义声明了某个数组类型Tsize(size为常量)的变量a,编译器在编译时会根据数组的定义给这个变量a连续分配一块大小为sizeof(T)*size的内存空间,并将这块内存空间的首地址装入数组名中。因此,C+中的数组是静态的并具有固定尺寸的一种数据结构,它常用于对一批同类型量的组织与操作。,C+只允许定义大小固定的静态、矩形的一维或多维数组(注意:数组尺寸不允许在运行时改变)。若需要动态数组(即数组尺寸在运行时可变),请用C+标准类库中的vector类(vector类的详细内容见本书第三部分)。 定义数组时,数组类型定义中

13、的size(数组元素的个数或称数组的尺寸)可以不给出,而交由编译程序推断出来,但此时必须在定义声明中对数组进行初始化,初始值的个数即为数组的size。例如:,int v1 = 1, 2, 3, 4; /int4 v1; char v2 = a, b, c, 0; /char4 v2; int i, j, k; int* v3 = 在定义多维数组时,语法上规定:其第一维的大小可以不给出,但除第一维以外的维数大小在定义时一定要给出。因为C+对多维数组的内存分配仍然是一块连续的内存空间,但C+是“按行”进行内存分配的(某些语言是“按列”进行分配的,如Fortran语言)。以二维数组为例,若不指定第二

14、维的尺寸,编译器将无法推断和检查所分配的内存。例如:,float f3=1,2,3,4,5,6; /正确!编译器推断为2行3列的float型数组 int a4=1,2,3,4,5,6,7,8; /正确!编译器推断为2行4列的int型数组 double d2=2,4,6,8,10; /错误!编译器无法推断内存分配量 数组类型定义时可给出size(整数常量/整型常量表达式),进而在定义声明中对数组进行初始化;初始化的元素个数不能大于size,但可以小于size(C+自动地对未给出初值的元素赋0)。例如: int v14 = 1, 2, 3, 4; /正确!int4 v1;,char v22 = a

15、, b, c, 0; /错误!初始值的个数4大于数组尺寸2 int i, j, k; int* v38 = ,如前所述,字面值0在不同的上下文环境中具有不同的类型,而不同类型的0在不同的上下文环境中又有不同的语义。例如,0对于整型而言,就是0;对于指针T*而言,它表示空指针;对于字符串char*而言,它是串结束符。因此,采用系统默认的0赋值,在某些情况下可能偏离编程者的本意,有时是十分危险的! 在C+中,对于全局或静态的(static)数组变量,当用户不赋初值时,系统自动赋初值0,局部数组系统不赋初值。,5.2.2 字符串字面值 由于应用中常常采用char*的变量或char数组变量存储一字符串常量,故在此引入字符串字面值的概念。 一个字符串字面值是由一对双引号括起来的一串字符。例如,“I am a student.” 就是一个合法的C+字符串字面值。 一个字符串字面值的长度等于其中所包含的字符个数加1(串结束符0);每个字符串字面值以字符0 (值等于0)作为串结束符。因此有: size

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

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