-
-
[原创]数组名和指针
-
发表于:
2011-1-9 10:17
7547
-
【阅读前】
本文是妆台秋思个人理解。毕竟操作系统设计人不是我(^_^ ^_^),我认为内存访问规则制定代表是微软。若有纰漏,请指出。
【相同点】
数组名本身就是指针,都涉及到系统底层的存储管理。对于进行系统底层或涉及到系统底层的应用程序编程,能应用于数组名的内存定位方法(通俗的说是寻找定位数组元素)也能应用于指针。例如:
const int a[2]={1,2};
int *b=a;
用b[0]也能找到“1”。获取当前b的地址是:&b,获得a的地址是:b或者a。获得元素“2”的地址是a+sizeof(int)
【不同点】
主要集中在分配的内存上面。数组名没有自己的内存空间,它的地址也是第一个元素的地址。而指针则有sizeof(指针类型)大小的空间,例如:
typedef struct aa
{
int a;
int b;
int *c;
struct aa a*;
}bb,*cc;
bb bbExam;
cc ccExam;
此时bbExam得到的存储空间与ccExam是相同的,都是sizeof(int)+sizeof(int)+sizeof(int)+sizeof(bb),sizeof(bb)=(sizeof(int)+sizeof(int)+sizeof(int))*2。但是这个情况:
bb bbExam[10];
cc ccExam;
则是不同的。前者是后者的10倍。
【指针的一个重要应用】
经常出现这样的情况:需要用到数组,但是数组的维数或者长度(数组元素个数)需要变动。普通的方法无法变动维数和长度,于是要用到指针,动态申请内存:
ccExam=(cc)malloc(sizeof(bb))或者:ccExam=(bb*)malloc(sizeof(bb))
删除数组元素:
free(ccExam)
加入数组:
&bbExam[1]=ccExam
【内存读或写错误】
指针用来存储地址,而不是用来存储数据的,例如以下是正确的:
bb bbExam[2]={0,0,0,0xFFFFFFFF,1,1,1,0xBBBBBBBB};
cc ccExam=bbExam;//或者:cc ccExam=&bbExam[0];
bb ddExam[2];
bbExam=ccExam;
以下是错误的:
cc ccExam;
bb ddExam[2];
ddExam=ccExam;
编译时不报错,因为语法确实没有错误。但是一运行就要出错:根据ccExam记录的地址访问数据导致访问当前程序没有权限访问的内存,它被操作系统拦截,并报出内存读错误。当前,只要将ccExam事先赋值为当前程序运行时所包含的内存地址就解决了,不过这样做没有意义。所以指针如果没有特殊用途,最好要初始化。肯定不能这样初始化:
cc ccExam=0x00000000;
00000000,这个地址是操作系统在使用的,0x00000000~0x000000FF一般存放中断向量表,操作系统肯定要拦截的。假设操作系统拦截失败,结果就是蓝屏或者整个系统死机了(具体什么结果要看这个程序要做什么事情了)。应该这样初始化:
int a=0;
int *p=&a;
声明变量a时,就获得了一部分有权访问的内存了。如果觉得初始化烦人,那么,int *p=NULL或者只要指针赋值(是当前有权访问的地址)之前不使用它,就不会出错。
【指针类型】
指针本身不是一个独立的类型,不能用它来声明变量。需要借助其它实体类型才能声明变量。可以这么理解:指针用来告诉来访者这里存储的是值的地址,而不是值本身。
【二重指针以及多重指针】
指针产生原因包括数据处理过程中需要知道数据所在位置(也就是地址),但是同是不能影响数据本身,所以产生了用来记录数据地址的变量。数据类型本身是人为规定的,其约束方法就像HTTP协议约束方法一样。如果有人不服,那么他就不能用现成的,数据类型需要他自己去制定了。如果需要记录地址的数据本身是指针,那么该指针是多重指针。常见的有二重指针。有学者论证三重指针以及更深层次的指针没有应用意义,所以我们也只需要了解一下定义。就我个人而言,写了这么多程序,确实没有用过三重以及更深层次的指针。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课