首页
社区
课程
招聘
[原创]数组名和指针
发表于: 2011-1-9 10:17 7546

[原创]数组名和指针

2011-1-9 10:17
7546

  【阅读前】

  本文是妆台秋思个人理解。毕竟操作系统设计人不是我(^_^ ^_^),我认为内存访问规则制定代表是微软。若有纰漏,请指出。

  【相同点】

  数组名本身就是指针,都涉及到系统底层的存储管理。对于进行系统底层或涉及到系统底层的应用程序编程,能应用于数组名的内存定位方法(通俗的说是寻找定位数组元素)也能应用于指针。例如:

  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直播授课

收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 348
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
  struct  在无成员的情况下会占1字节的。
2011-1-9 22:01
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
3
视编译器而定。
GCC 下是零字节大小。

为了及时发现错误,对于C++来说,变量最好是用到时才定义:
HANDLE hFile = CreateFile(....); // 这里需要用到 hFile 接收 CreateFile 的返回值,定义 hFile 后即时使用。
对于 C 来说,所有的变量都要提前定义才行。
变量的初始化要视变量的类型而定.
对于指针,应当指向空地址(不是地址为零,而是不指向任何地址)。

int *p = NULL;
2011-1-9 22:05
0
雪    币: 348
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
么用过GCC
一般v6 vs08
2011-1-9 22:16
0
雪    币: 66
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习……^_^ ^_^
2011-1-10 10:58
0
雪    币: 245
活跃值: (93)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
你第一段就有问题  “内存访问规则是微软制定的” 真不知道你这么理解是因为什么 x86自带mmu都被你河蟹了.....
2011-1-10 12:30
0
雪    币: 154
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
对二重的指针的解释没看明白。。。。。。
一会地址,一会内容。。。
糊涂了。。。。
2011-1-10 15:54
0
雪    币: 66
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
呵呵,至少对于WINDOWS,所有内存都有它的访问权限。我知道你说的是CPU保护模式下对内存访问的管制,但是管制作用的发挥还是由操作系统来实现,不是吗?
2011-1-10 17:43
0
雪    币: 72
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
陋室空堂~当年笏满床~衰草枯杨~曾为歌舞场~
蛛丝儿结满雕梁~绿纱今又糊在蓬窗上~
说什么脂正浓~粉正香~如何两鬃又成霜~
昨日黄土垅头送白骨~今宵红绡帐底卧鸳鸯~
金满箱~银满箱~转眼乞丐人皆谤~
正叹他人命不长~哪知自己归来丧~
训有方~保不定日后做强梁~
择膏粱~谁承望流落在烟花巷~
因嫌纱帽小~致使锁枷扛~
昨怜破袄寒~今嫌紫蟒长~
乱烘烘你方唱罢我登场~反认他乡是故乡~
甚荒唐~到头来都是为他人做嫁衣裳~
2011-1-20 14:56
0
雪    币: 245
活跃值: (93)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
10
数组名和指针本来没什么关系。

数组名 是一块内存地址的【名字】 就像门牌号指明了门的位置,又贴在门上面。
指针   是使用一块内存地址的【工具】 就像一把钥匙 可以开这个门 但是它和门没有任何关系

指针是真实存在计算机内存中的 比如
int a;
int *p =&a;
计算机确实有一个地方存放p (a的地址)

数组名是不存在与计算机内存中的 比如
int b[4]={1,2,3,4};
计算机没有一块地方来保存b这个东西

这个就是数组和指针在本质上的区别
而你举得例子 只是说明它们在语法上的通用性
这仅仅是为了方便你用  绝对不是本质 比如
int c[4] ={1,2,3,4};
int * p =c;
这时候你确实可以p[3](甚至你可以3

) 它们只是在形式上 = *(p+3) 此外不代表任何含义

2012-3-17 16:49
0
游客
登录 | 注册 方可回帖
返回
//