Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16486
  • 博文数量: 11
  • 博客积分: 410
  • 博客等级: 下士
  • 技术积分: 105
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-04 21:16
文章分类

全部博文(11)

文章存档

2011年(1)

2008年(10)

我的朋友
最近访客

分类: C/C++

2008-05-12 10:14:36

看了《c专家编程》,对指针和数组的区别有了比较清晰的了解。

先写一个小程序

#include <stdio.h>
int main()
{
        char a[2], *p;
        printf("a:%x\n&p:%x\n", (int)a, (int)&p);
        return 0;
}


结果
a:bfa10942
&p:bfa1093c

p和a都保存在栈中,内存布局是这样的(此时p并未初始化,但这个不影响下面的讨论),
          |   p  |  &p = 0xbfa1093c
          | a[0] |  a = 0xbfa10942
          | a[1] |  a+1 = 0xbfa10943
看到这个布局,不难理解为什么数组的指针为常量而不能改变,因为a的含义跟&p其实是类似的,为非左值,正如我们也无法修改&p的值。


另外一个比较明显的区别是指针和数组的寻址方式:
修改程序,加上

p = a;
a[0] = 0, a[1] = 0;


指针:
获得p[1]的值
1.找到指针p在栈中的位置,即&p,读取其中的内容p。
2.找到地址为p的内存位置,即为0xbfa10942。
3.然后偏移1位(偏移大小对应于指针类型),即为0xbfa10943,读取其中的内容0。
数组:
获取a[1]的值
1.找到a在栈中的位置0xbfa10942。
2.向下偏移一位,0xbfa10943,读取其中内容,即为0。

再举个书中的例子,我觉得这个例子能更能将两者的区别体现出来。
在a.c中 定义 char a[2] = {0, 1};
在b.c中   定义 extern char* p;
此时若在b.c中 读取 p[1]中的内容,会产生什么样的后果呢?

因为extern是声明,并未在栈中给p分配一个实际的空间,此时p的保存位置其实就是a所在位置,即&p == a(0xbfa10942),然后进行对p[1]的寻找。
系统认为p是一个指针,则会按照指针的方式来寻找p[1]。
1.找到&p,读取内容p,而&p中的内容即为 a[0],即此时结果为 p = 0;
2.找到地址为p的内存位置,即找到内存地址为0的地方。
3.然后偏移1位,访问地址为0x1的内存,出错。(或者为程序崩溃,或者为结果错误)

同理,若原定义为指针,而声明为数组,也会出现类似的问题。所以最好的办法是,一一对应,才会避免出现上面的错误。
阅读(556) | 评论(0) | 转发(0) |
0

上一篇:UNIX版本介绍

下一篇:dhcpd 分配IP失败

给主人留下些什么吧!~~