=。=据说这个问题是面试题常见问题,,所以要好好整理下。
-----------------------------------------------------------------------------------------------------------
首先先看一个问题↓
-------------------------------------------
假设文件a.c有如下定义:
int a[8] = {1,2,3,4,5,6};
int *p = a;
假设有另一文件b.c有如下语句:
extern int*a;
exter int p[];
int x,y;
x = a[3];
y = p[3];
现在运行程序,结果会如何呢?
-----------------------------------------
程序运行崩溃。
b.c中a被当作指针变量。所以它提取指针值(指针保存的是地址,于是a中保存的值被当作地址),并加上12(也就是3×sizeof(int))实现对数据的间接访问。但是通过定义可以知道a是数组名。
而数组名a只有以下两种情况下表示整个数组:
(1)在定义数组的同一函数内部求sizeof(a)表示整个数组字节数。
(2)&a + 1 表示在a数组地址后的一个数组
其他情况下一维数组名表示数组首元素地址。
所以在这里a是数组起始位置。指针获得的是第一个元素值,这个值与12相加将其结果当作一个地址并进行访问。可能会导致错误或随机值。
把p当作数组名,p的地址加上12,就是要访问的地址。然而定义告诉我们,p其实是个指针,所以y=p[3]的操作会取得一个值,它是一个不相关值。
咳咳。。这样说有点抽象了,,画个图帮助了解。假设他们的地址是这个样子的:
------------------------------------------------------------------------------------------------------------
-所以指针和数组是有很大区别的。
数组通过下标可以很容易的实现对数据的访问,前面也说了在两种特殊情况下数组名代表整个数组,其他情况下都表示数组的首地址。
也就是说呢a的地址和a[0]是一样的~ p = a;等价于p = &a[0];
可以通过以下更好的了解数组名:
int main() { int a[8] = {0}; printf("a-------->%x\n", a); printf("&a------->%x\n", &a); printf("&a[0]---->%x\n", &a[0]); printf("a+1------>%x\n", a + 1); printf("&a+1----->%x\n", &a + 1); printf("&a[0]+1-->%x\n", &a[0]+1); }
![](https://img-blog.csdn.net/20170902154901432?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzU0OTI4NTc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
=。=换成10进制可以看得更清楚,但是既然写了就懒得改了。
数组一组地址有序的数据的集合,对应一块连续的内存,我们无法改变数组的地址,但是可以改变它的内容。
访问数组a的第i个元素可以用 a[i] *(a+i) 数组的访问时通过偏移量实现的。
另外,再把数组当参数传入的时候,数组会退化成指针,表示数组首地址
指针指向变量单元,其实指针就是地址啦=v=存放地址的变量就是指针变量!
别把指针和指针变量弄混,一个地址一个是变量。
指针变量包含两方面:(1)存储的地址(2)存储单元的类型
数组元素的指针就是数组元素的地址。
通过指针访问数据的过程是这样的~首先访问指针常量的值,这个值呢他表示一个地址,所以接下来要找到这个地址访问地址内的数据。