我关于数组的一些概念的理解
int a[10]={1,2,3,4,5,6,7,8,9,10};
以上操作是:程序中声明了一个整型数组(同时对数组进行了初始化)。该数组中包含有10个整型变量,而数组名a是数组的标识。数组的建立是程序根据你所提供的详细信息,在内存中建立一个能够保存10个整型数据的连续内存空间(自动变量的存储是在堆栈中),之后创建数组名与数组的关联;
数组名在表达式中可以被当做一个指针常量来对待,对于数组名的计算大部分是对其所存数组首地址的应用;这是它经常被当做指针常量的原因;还有些特殊情况下数组名不代表该数组的首位地址,比如:sizeof(数组名)其结果是,该数组占用内存的大小;引申到上面的例子sizeof(a)的值应该是 10个整型变量占内存的大小(不同的系统该单位大小不同,turbo C 占2个字节大小);此时的数组名就不是一个指针常量;还有种情况,当&与数组名在一起的时候,它所代表的是一个指向数组的指针,(*p)【】;只有这两种情况下数组名没有被当做指针常量来对待;
对于数组中元素的访问可以通过两种形式 :
1、下标法 a[2]表示是数组的第三个元素的值(整型的3)
2、 通过地址法访问数组元素 既 *(a+2)也代表整型数据3 数组中的第三个变量
这些事如何发生的呢?假设数组a的首地址是100,系统将下标数字与整型数据的存储单位相乘(我的系统上一个整型数据的单位 是2个字节)计算2*2得到的结果是4与数组名的地址相加,得到104这个地址,系统从这个地址中取值并用整型数据的方式描述取到的值,这就是数组,取值过程;
而关于指针有如下概念
int *b=a;
b是一个指向整型变量的指针,代表b的内存中存储的是一个地址值(数组a的首地址);如果想通过指针b访问数组a中的元素,可以通过间接引用的方式 如*b 就代表了数组a的第一元素 a[0] 的值 1;如果想访问第三个元素,指针操作如下 *(b+2)实际这个表达式将指针,向高位偏移两个单位(不同系统单位字节数不同),指向该地址后使用*引用该地址内的数值;
指针也可以用下标法访问数组中的元素:
b【2】的含义等同于*(b+2)都是将地址指向偏移两个单位并引用该地址内的数值;详细些讲就是 系统先将指针b中所保存的值(地址值(系统将b中保存的数据按地址数据解释))提取出来,然后用这个地址与 2个单位的整型字节数相加(我的系统是一个整型是2个字节),也就是说如果原有地址是100的话,地址+2实际上是将地址偏移了4个字节,此时的指针指向了地址104,此时间接引用符*或【】起作用了,把该地址中的值取出,并用整型方式解释该数据;
问题:
//假如同一个文件下的不同源文件内有如下声明 何解?
源文件1下有声明:
int a[10];
int *b=a;
源文件2下有代码:
extern int *a;
extern int b[];
.....
.....
x=a[3];
y=b[3];
在源文件2中
数组a被解释成一个指针!
指针b被解释成一个数组名!
他们被引用后的值是否正确?如果不正确为什么?
上面我们提到过指针的间接引用,是系统先从指针变量所在的地址中取出地址值,然后再把该地址加上3(下标)*sizeof(int)的乘积,最后将计算出的地址中的数据取出,按整型方式解释;现在被系统错认为指针的数组名a的地址里面存的是什么呢?是一个整型数据,是数组a的第一个元素的值,而系统确非要把它作为地址解释,还要给他加上偏移量,最可怕的是还要在这个莫名其妙的地址中取数据,按整型解释;结果呢?可能取到的是一个垃圾数据,也可能更糟糕,引用了系统的关键数据并更改,引起严重后果;
现在我们来研究一下,被解释成数组的指针b的情况是怎么样呢?数组所在的地址,也就是要偏移的起点,(int array[100];)系统会直接把下标3*sizeof(int)加在数组地址上,糟糕的是现在被解释成数组指针b的地址 与数组一点关系都没有!你要按这个地址偏移一个标准量,然后再取出那个莫名其妙的地址中的值,会有什么好结果么?答案是肯定的,所以对于数组名和指针的理解才是利用好他们的关键;
同上面的分析我们不难得出一个结论,指针与数组名有相似之处,但也存在着差异;只有充分的理解他们各自原理与功能才能在实际应用中很好的使用的他们,
另外他们在不同使用地点也有着不同的效果,在这里就不一一赘述了,此文仅就 pointer on C 中 第八章习题 (纠结了两天后的理解)阐述我个人的理解和感悟;