Chinaunix首页 | 论坛 | 博客
  • 博客访问: 708020
  • 博文数量: 161
  • 博客积分: 2998
  • 博客等级: 少校
  • 技术积分: 1697
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-28 09:39
文章分类

全部博文(161)

文章存档

2012年(6)

2011年(120)

2010年(35)

分类: C/C++

2011-06-01 19:53:56

声明一个数组时,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,它的值时一个常量,指向这段空间的起始位置。
数组名是符号地址常量,在编译时求值并存在编译器的符号表里面,其值就是个内存地址;所以可以认为程序没有给a分配空间,数组名只是代表了那个数组空间;与指针不一样,指针指向一块空间,同时指针本身也存储在某个空间;可以认为数组名存在在符号表里,符号表是编译器用的,我们管不到;a和&a值是一样的,本来对常量取地址是非法的,但是标准组织没有定对数组名取地址是非法还是合法,所以因编译器而异,VC是合法的。
C专家编程里解释的很好:

经典的错误:在一个文件定义了数组,却在另外一个文件声明其为指针。代码如下:
/*File name: main.c*/
extern int* array; /*声明指针*/
int main(void)
{
 array[0]=1; /*用指针访问数据*/
 return 0;
}
 
/*File name: def.c*/
int array[5]={0}; /*定义的却是数组*/ 

1。编译器对数组名和指针变量的处理方式
编译器在编译时会产生一个符号表,记录了符号名和它的地址。对于指针变量,这显然很好理解。而数组名就不那么明显了,它仅仅是一个符号而已,何来地址?编译器是这样处理的,它记录了array[0]的地址;这和我们通常的理解也是一样的。
2。带下标形式的数组和指针寻址方式
(1)数组情形
char a[9]="abcdefgh";
...
c=a[i];
在编译期,会在符号表中创建这样一条记录:
name:a address:9980
要获取a[i]的值分两个步骤:
step 1:取得i的值并和9980相加
step 2:在内存地址(9980+i)处取其内容
 
(2)指针情形
char* p="abcdefgh";
...
c=p[i];
在编译期,会在符号表中创建这样一条记录:
name:p address:4624
要获取p[i]的值分三个步骤:
step 1:在内存地址4624处取其内容,比如说“5081”
step 2:取得i的值并和5081相加
step 3:在内存地址(5081+i)取其内容
 
现在有了这些知识,前面出现的错误就很好解决了。在def.c中定义array是一个int型数组,在符号表中就会有把array和array[0]的地址关联起来。而在main.c中却把把array看作是一个int型指针,于是乎按照上面介绍的指针寻址方式,把符号表中array的地址(即&array[0])中的内容当作指针来寻址,这显然是不对的。
阅读(2908) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~