本章主要通过不同文件头部引用的问题讲述了数组和指针的一些区别
考虑以下两个文件的头部声明
1 | // 文件1 |
在文件1中定义了一个名为mango
的数组,文件2中声明了一个名为mango
的外部指针变量
extern对象声明告诉编译器对象的类型和名字,对象的内存分配则在别处进行。由于并未在声明中为数组分配内存,所以并不需要提供关于数组长度的信息。对于多维数组,需要提供除最左边一维之外其他维的长度—-这就给编译器足够的信息产生相应的代码
数组和指针的一个重要区别在于数组的地址在编译的时候就已经知道了,所以对于一个具体的数组变量a
,编译器的符号表存的就是数组的起始地址。而对于某一个具体的指针变量p
来说,编译的时候并不知道它所要指向的具体内容,需要进行解引用,所以编译器的符号表只知道这变量p
本身所在的地址,然后每次解引用的时候需要进行以下几个步骤
- 根据符号表中
p
的地址读取变量p
的内容,这是一次解引用 - 根据
p
的内容(一个地址),找到其所指向的位置 - 将上述的地址加上可能的偏移量,得到最终需要访问的地址,并取得其内容,这又是一次解引用
所以当发生上述两个文件的头部声明的情况的时候。由于mango
被声明为指针,那么就将会按照上述的3点来进行处理
- 由于
mango
在符号表中存放的就是数组的起始位置,所以对其进行解引用,得到数组的第一个元素,一个int值 - 将这个int值作为地址,找到其所指向的位置,这里就错的离谱了
- xxxx
一般来说对于数组和指针声明(extern
)和定义的情况有以下四种
- 声明为指针,定义为指针
- 声明为指针,定义为数组
- 声明为数组,定义为指针
- 声明为数组,定义为数组
其中1,4都不会有问题,3,虽然可以正常工作,但其内部的机理和1,4还是不太相同,有点刚好碰对的感觉?2就是刚刚讲的例子,会出错
感觉主要的差异还是由于编译器存储方式造成的,由于数组的地址在编译的时候就知道了,所以符号表里面直接就存了地址,但是指针却不同。