复杂数据及运算—指针_第1页
复杂数据及运算—指针_第2页
复杂数据及运算—指针_第3页
复杂数据及运算—指针_第4页
复杂数据及运算—指针_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

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

文档简介

1、C+教程第四章 复杂数据及运算清华大学 郑 莉4.2指针 为了操作地址!一点忠告! C/C+可以直接操作内存地址。 指针就是为了地址操作而存在的。 指针是复杂又容易出错的。 在不是必须不是必须使用指针的场合,不推荐用指针。 我们学习指针不是为了到处用指针,而是在需要用的时候使用。 我们自己写程序的时候,在确保程序实现功能的在确保程序实现功能的前提下,前提下,代码是越简单越好,而不是技巧越多,越复杂越好!本节的学习 本节除了动态内存分配,其余所有程序例题,其实都可以不需要指针。 只所以用指针是为了帮助我们理解指针的用法。 本节的学习,一定要了解一点内存的知识。 内存单元的地址 C+各种基本数据类

2、型的长度(字节)4.2.1 数据在内存中的地址 内存空间的访问方式 通过变量名访问通过变量名访问 通过地址访问通过地址访问5程序中: int i; 内存中每个字节有一个编号-地址地址.20012002内存0 i 编译或函数调用时为其分配内存单元变量是对程序中数据存储空间的抽象变量与地址2000如何获得变量的地址 地址运算 取地址运算符:& 数组的起始地址 数组名字既是数组的起始地址,因此数组名是地址常量。7例4-5:观察变量在内存中的地址#includeusing namespace std;int main()int intVal=1;double dVal=2.0;int inta

3、rray3=0,1,2;cout&intVal:intValendl;cout&dVal:dValendl;coutintarray:endl;cout&intarray0:intarray0endl;return 0;84.2 数组4.2.1数据在内存中的地址运行结果:运行结果:0013FF7C:10013FF74:20013FF68:0013FF68:0例4-5(续)4.2 数组4.2.1数据在内存中的地址对例4_5的分析:如何获得变量的地址1intVal地址:&intVal2dVal地址:&dVal102intArray intArray是数组名,

4、代表的是数组的起始地址,也就是第一个元素的地址。 intArrayi,用下标法访问数组的元素。 intArray0是数组的第一个元素,该元素的地址是&intArray0。 所以intArray, &intArray0,所存放的地址是一样的。&intArray0 一旦定义了一个数组,数组名存放的就是数组的起始地址,也就是一个地址类型的数据。 在生存期内,整个数组在内存中的所占用的存储空间是不变的,地址是不变的,所以数组名是一个地址类型的常量常量。对一维数组的再探讨 一维数组有个关键问题:下标不可以越界。但是下标不可以越界。但是如果越界编译器并不能检查出错误。如果越界编译器

5、并不能检查出错误。 从地址的角度来考虑这个问题。102intArray&intArray0&intArray1&intArray2&intArray3超出数组范围可能对其他数据产生破坏例4-6:观察一维数组在内存中的存储#include #include using namespace std;const int size=5; int main() int arraysize; int i;for (i=0; isize; i+) arrayi=i;for (i=0; isize; i+) coutsetw(10)arrayi;coutendl;for (i=

6、0; isize; i+) coutsetw(10)&arrayi;coutendl; cout&array5: &array5endl; 144.2 数组4.2.1数据在内存中的地址运行结果:运行结果: 0 1 2 3 4 0012FF6C 0012FF70 0012FF74 0012FF78 0012FF7C &array5: 0012FF80例4-6(续)对例4_6的分析 通过本例的输出,可以看出数组元素是顺序存储的。 &array5,其实已经不是array数组中的元素的地址了。 增加语句:array5=100; 在编译时不会出现错误信息; 运行后

7、得到的错误信息,是操作系统发出的。例4-7:观察多维数组在内存中的存储#include #include using namespace std;const int nrow=3;const int ncol=2; int main() int arraynrowncol; int i;for (i=0; inrow; i+) for (int j=0; jncol; j+) arrayij=i+j;for ( i=0; inrow; i+) for (int j=0; jncol; j+) coutsetw(3)arrayijsetw(10)&arrayij;coutendl;174

8、.2 数组4.2.1数据在内存中的地址运行结果:运行结果: 0 0012FF68 1 0012FF6C 1 0012FF70 2 0012FF74 2 0012FF78 3 0012FF7C例4-7(续)4.2 数组4.2.1数据在内存中的地址对例4_7的分析 通过本例的输出,可以看出多维数组元素是按行存储的。二维数组在内存中的存储 占据一片连续存储区 int a43a00 a01 a02a10 a11 a12a20 a21 a22a30 a31 a32按行存放按行存放第第0 行行a00a01a02a10a11a12第第 1 行行a30a31a32第第 3 行行.内存内存4.2.1 结束语 这

9、个部分通过3个例子,展示了数据在内存中如何存放,特别强调了数组的存放。 普通变量:用取地址运算符&获得地址。 数组:数组名就是数组的起始地址。 那么,地址取出来做什么?刚学过的3个例子中,地址取出来只是做了输出。 问题1:为什么要使用地址? 问题2:如何使用地址?问题1:为什么要使用地址?在C+中,除了用变量名,还可以直接使用地址来访问内存单元。这样做的原因:1 有些场合更高效2 动态分配内存时必须用地址访问3 有效的表示复杂数据结构。问题2:如何使用地址? 用于存放地址的变量就是指针类型的变量。4.2.2 指针及指针运算定义指针 * Name; T为类型,表示指针所指对象的类型; *

10、表示此变量类型为指/针; Name为定义指针的名称。指针变量赋初值 1. 在声明指针的同时进行初始化赋值; 2. 在声明之后,使用赋值表达式语句为指针赋值。244.2 数组程序中: int i; 内存中每个字节有一个编号-地址地址.20012002内存0 i 编译或函数调用时为其分配内存单元变量是对程序中数据存储空间的抽象1 变量与地址2000.2000整型变量i10变量i_pointer2004v指针:一个变量的地址。v指针变量:专门用来存放地址的变量叫指针变量,它的值也可以是数组或函数的地址 。2000指针指针变量 变量的内容 变量的地址2. 指针与指针变量.1. 指针变量与其所指向的变量

11、之间的关系2. 指针变量的定义v一般形式: 数据类型 *指针名;3变量i2000i_pointer*i_pointeri*i_pointer&ii_pointeri=3;*i_pointer=3合法标识符指针的目标变量的数据类型表示定义指针变量不是乘法运算符*例 int *p1,*p2; float *q ; char *name;注意:1、int *p1, *p2; 与 int *p1, p2;不一样。2、指针变量名是p1,p2 ,不是*p1,*p2。3、指针变量只能指向定义时所规定类型的变量。4、指针变量定义后,变量值不确定,应用前必须先赋值。3. 指针变量的定义含义: 取变量的地

12、址单目运算符结合性:自右向左含义: 从某个地址中获取数据单目运算符结合性:自右向左两者关系:互为逆运算4. 取地址运算符&与指针运算符* *.20002010整型变量i10变量i_pointer20042000指针变量i_pointer-指针变量,它的内容是地址量20002000*i_pointer-指针的目标变量i,它的内容是数据10&i_pointer-指针变量占用内存的地址:20102010i_pointer &i &(*i_pointer)i *i_pointer *(&i)指针运算符示例=.例 main( ) int i=10; int *p;

13、 *p=i; cout*p; 不可不可以危以危险!险!例 main( ) int i=10,k; int *p; p=&k; *p=i; cout*p; .20002010整型变量i10指针变量p2004随机值5. 指针变量必须先赋值,再使用!.空指针:v定义:指针变量值为零 例如: int * p=0; p指向地址为0的内存单元;系统保证该单元不作它用;表示指针变量的值没有意义。lP为空指针与未对p赋值不同u避免指针变量的非法引用6. 空指针例4-8:定义指针并通过指针访问变量#include using namespace std; int main() int num(23);i

14、nt* P_num=0;P_num=# coutthe integer is: numendl;coutthe number that is pointed to is: *P_numendl;coutthe address of the number is: P_numendl;324.2 数组4.2.2指针及指针运算运行结果:运行结果:the integer is: 23the number that is pointed to is: 23the address of the number is: 0012FF7C例4-8(续)4.2 数组4.2.2指针及指针运算对例4_

15、8的分析 通过本例的,学习 定义指针 给指针赋值 使用指针 空指针指针初始化 int* P_num=0; P_num=# 先定义指针,再赋值 int* P_num=# 定义指针同时初始化将地址值赋给指针变量例 int i; int *p=&i;变量必须已说明过;并要求两者类型一致。例 int *p=&i; int i;例 int i; int *p=&i; int *q=p;用已初始化指针变量作初值一般形式: 数据类型 *指针名=初始地址值;7. 指针变量的初始化例 i=3; -直接访问指针变量.20002010整型变量i10变量i_po

16、inter200420003例 *i_pointer=20; -间接访问20v 直接访问v 间接访问8. 直接访问与间接访问.9.对指针变量的操作C+语言程序设计清华大学 郑莉指针变量的算术运算指针变量的算术运算l指针与整数的加减运算指针与整数的加减运算指针p加上或减去n,其意义是指针当前指向位置的前方或后方第n个数据的地址。这种运算的结果值取决于指针指向的数据类型。l指针加一,减一运算指针加一,减一运算指向下一个或前一个数据。例如:y=*p+ 相当于 y=*(p+) 指 针p-1pp+1p+2*(p-1)或者p-1*p或者p-0*(p+1)或者p1*(p+2)或者p2intint * *p;

17、p;40C+语言程序设计清华大学 郑莉注意:注意:l指针做算术运算指针做算术运算l有意义的场合:访问连续数据序列,有意义的场合:访问连续数据序列,例如数组。例如数组。l其他情况不要用,不仅没意义,还容其他情况不要用,不仅没意义,还容易带来危险操作。易带来危险操作。C+语言程序设计清华大学 郑莉l关系运算关系运算指向相同类型数据的指针之间可以进行各种关系运算。指向不同数据类型的指针,以及指针与一般指向不同数据类型的指针,以及指针与一般整数变量之间的关系运算是无意义的。整数变量之间的关系运算是无意义的。指针可以和零之间进行等于或不等于的关系运算。例如:p=0或p!=0,判断是否为空指针l赋值运算赋

18、值运算向指针变量赋的值必须是地址常量或变量地址常量或变量,不能是普通整数不能是普通整数。但可以赋值为整数0,表示空指针。例4-9:通过指针访问有序的批量数据#include #include using namespace std;const int size=6; int main() int arraysize=2,4,13,7,9,21;int *P_array=array;coutthe sequence is:endl;while (P_array array+size) coutsetw(4)*P_array;P_array+;coutendl;P_array=array;cout

19、the forth number of the sequence is: endl;cout*(P_array+3)endl;return 0;434.2 数组4.2.2指针及指针运算运行结果:运行结果:the sequence is: 2 4 13 7 9 21the forth number of the sequence is:7例4-9(续)4.2 数组4.2.2指针及指针运算对例4_9的分析 指针可以和整数进行加减运算,运算规则比较特殊。 指针加减运算的结果与指针类型密切相关。 指针加1的效果是使指针指向下一个完整数据的起始地址。 利用指针的这个特性,通过指针的不断增值,依次顺序访问

20、有序的批量数据。指针的算术运算 一般来讲,指针的算术运算是和数组的使用相联系的,因为只有在使用数组时,才会得到连续分布的可操作内存空间。 常用的比较运算: 如果两个同类型的指针相等,表示这两个指针是指向同一个地址的。 如果一个指针等于0,表示这个指针是空指针。C+语言程序设计清华大学 郑莉指向数组元素的指针指向数组元素的指针l声明与赋值声明与赋值例:int a10, *pa; pa=&a0; 或 pa=a;l通过指针引用数组元素通过指针引用数组元素经过上述声明及赋值后:*pa就是a0,*(pa+1)就是a1,. ,*(pa+i)就是ai.ai, *(pa+i), *(a+i), pai

21、都是等效的。不能写不能写 a+a+,因为因为a a是数组首地址是常量。是数组首地址是常量。 指 针C+语言程序设计清华大学 郑莉为什么用指针处理数组为什么用指针处理数组l与后面要学习的动态内存分配数组有与后面要学习的动态内存分配数组有关。关。l下面的例子,用了三种方法,对比,下面的例子,用了三种方法,对比,大家可以发现:大家可以发现: 完成了同样的功能,使用指针也并没有更方便。l包括例包括例4_9,完全可以不用指针,大,完全可以不用指针,大家思考如果不用指针,此题怎么写。家思考如果不用指针,此题怎么写。C+语言程序设计清华大学 郑莉设有一个设有一个int型数组型数组a,有有10个元素。用个元素

22、。用三种方法输出各元素:三种方法输出各元素: 使用数组名和下标 使用数组名和指针运算 使用指针变量 指 针intint main() main() int a10; int a10; int i; int i; for(i=0; i10; i+) for(i=0; iai;ai; coutcoutendlendl; ; for(i=0; i10; i+) for(i=0; i10; i+) coutcoutaiai; ; 使用数组名和下标使用数组名和下标51intint main() main() int a10; int a10; int i; int i; for(i=0; i10; i+

23、) for(i=0; iai;ai; coutcoutendlendl; ; for(i=0; i10; i+) for(i=0; i10; i+) coutcout* *(a+i)(a+i); ; 使用数组名指针运算使用数组名指针运算52使用指针变量使用指针变量intint main() main() int a10; int a10; int int * *p,ip,i; for(i=0; i10; i+)for(i=0; iai;ai; coutcoutendlendl; ; for(p=a; p(a+10); p+) for(p=a; p(a+10); p+) coutcout* *p

24、 p; ; 53动态分配与释放内存空间 以静态方式定义的数组,其大小必须定义好,而且不可改变大小。 在运行时动态分配内存空间,一旦空间不再被使用,应该在程序中及时释放。 但是动态分配的内存空间,不可以命名,也就不能通过变量名来访问了,只能使用地址操作。4.2.2 指针及指针运算(续)内存的动态分配 动态分配单个变量的语法形式为:new T(初值列表); 动态分配一维数组的语法形式为:new T元素个数;内存的动态释放 释放单个变量空间的语法形式为:delete 指针名; 释放动态数组空间的语法形式为:delete 指针名;554.2 数组运算结果是为新分配空间的起始地址例4-10:实现一个在运行时确定大小的一维数组#include #include using namespace std; int main() int size;coutplease enter the number of the sequence: si

温馨提示

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

评论

0/150

提交评论