- 1、本文档共31页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
第三节、数组与指针 目标: 1. 一维数组与指针 2.数组越界 3.指针和堆的内存分配 4.丢失指针 一、一维数组与指针 1、什么是数组? 数组是一组数据存储单元,每个单元保存相同数据类 型,每个存储单元成为数组的一个元素。 2、什么是指针? 指针是一个变量,它保存了一个变量的地址。 首先我们看一下下面的例子: char a[10], *p; p=a; p是一个char类型的指针,它里面放的是数组a的首地址,即a[0];a这里有双重含义:地址,也可以看作是常量指针;里面包含了10个char元素。在这种情况下,指针可以完成数组的操作,例如,对于数组的访问,可以用指针进行,也可以像数组一样对数组单元赋值和取址。但是数组不能看做普通指针,应该理解成一个固定的地址,她是在编译期间确定的,也可以理解成常量指针。?但是,由于数组名的双重含义,决定了他自己的特性,不信请看下面的程序: #include iostream #include stdlib.h using namespace std; ?int main(int argc, char *argv[]) ?{??? int a[10]={1,2,3,4,5,6,7,8,9,10}, *p;??? p=a; ??? coutaendl;??? coutaendl;??? couta[0]endl; coutpendl;??? coutpendl;??? coutp[0]endl;???? getchar(); return 0; ?} 我们看到a, a , a[0]输出的结果都是一致的,他们都是数组的首地址,这里a体现的是指针的特性,a则体现了结构的特性。但是对于p来讲就不一样了,因为指针p在开始的时候开辟了一块自己的内存空间,经过p=a后,p里面放的是数组a的首地址,所以p和p[0]结果都是数组a的首地址,但是p则是指针p本身的内存地址。? 那么一维数组究竟是什么含义呢? 实际上,一维数组应该理解成一个线性表,他在内存中开辟了一块连续的内存空间。在对数组访问的时候,实际上,编译器做了一定的转换工作:数组名(数组的起始地址)加上相对于起始地址的相对量(由下标变量给出),得到要访问的数组元素的单元地址,然后再对计算出的单元地址的内容进行访问。例如a[3]被转换成*(a+3)。 由于数组是在编译期间确定,代表的是一块固定的内存空间,所以数组是不能够改变的,即a++,++a,a--,--a,a+=3,a-=3等都是不允许的,但是指针p做这些动作是毫无问题的。? 在win32系统下,任何类型的指针都占4个字节的内存空间。想想为什么? 答: 因为指针是是保存变量地址的变量,在win32下,32位地址,正好占用4字节宽。 二、数组越界 例如: 1: int a[10]; 2: int i; 3: i = 2; 4: for(int j = 0;j 3; j++)i--; 5: a[i]++; 6: printf(i = %d\n,i); 对于上述代码,在line4结束时,i值为-1,而当line5结束时,i为0;原因是a[-1]所在单元恰好是i所在单元。而c++不对数组越界作检查,而是按偏移去寻址。 数组越界有时候还是一种攻击手段,例如:我们如果要修改一个对象的虚函数表指针,由于虚函数表指针保存在对象中,是一个const类型的指针。常规的办法无法修改,但是我们可以通过数组越界的方法来修改它。呵呵。正所谓技术是一把双刃剑,就看你怎么用了。 三、指针和堆的内存分配 前面谈到无论什么类型的指针,win32下都是占4个字节 的内存空间。那么对于指针的类型,有什么作用呢? 答:指针的类型代表着指针内存空间中存储的变量的类 型,同时也是指针运算时的步长。 例如:char a[] = “hello”; char *p = a; p++; //p++时,对于char型,p向前迈进1个字节。 Int a[] = {1,2,3,4,5,6}; Int* p = a; P++; //p++时,对于int型,p向前迈进4个字节。 在前面,我们曾经提到一个进程的用户区分为4个部分, 全局/静态区、代码区、堆区、栈区。 对于这四个区的数据,我们都可以通过指针进行间接访 问。在C++中,申请和释放堆中分配的存贮空间,分别使用 new和delete的
文档评论(0)