数组名代表数组第一个元素的首地址!
数组名存着整个数组的开头地址,而数组元素的存储是在数组所开辟出来的内存空间(连续的空间)中从头往后存值的,所以数组名可看作一个指针(指向数组的开头),数组名存的值也就和数组第一个元素的值相同。
int a[5] = {1,2,3,4,5};
a, &a, &a[0]三者地址在数值上一样 ,所含意义不同!
a[0]------数组的第一个元素
a--------数组名a可看作指针a指向这个数组,存着数组的首地址;
&a----------对数组名取地址,其意义为:获取整个数组空间的地址(开头地址)
&a[0] ---------对首元素取地址,其意义为:获取第一元素的地址;
a + 1 ----
相当于一个指向数组a的指针往后位移一个元素(取决于数组的类型)的距离(即单个数组元素的所占内存大小)。
&a[0] + 1 -------含义与a + 1相同
&a + 1----------
相当于一个指向数组a的指针往后位移整个数组的距离(数组元素个数*数组类型的大小),即指针指向数组末尾的后一位的地址
具体事例演示:
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int i;
printf("数组a中的值为:");
for(i = 0; i < 5; i++)
{
printf("%d ", a[i]);
}
printf("\n\n");
printf(" a =%p, a地址上的值为:%d\n", a, *a);
printf(" &a =%p, &a地址上的值为:%d\n", &a, *(&a));
printf("&a[0] =%p, &a+1地址上的值为:%d\n", &a[0], *(&a[0]));
putchar('\n');
printf("三者加一后的变化:\n");
int *p = (int*)(&a+1);
printf(" a+1 =%p, a+1地址上的值为:%d\n", a+1, *(a+1));
printf(" &a+1 =%p, &a+1地址上的值为:%d\n", &a+1, *(&a+1));
printf("&a[0]+1 =%p, &a[0]+1地址上的值为:%d\n", &a[0]+1, *(&a[0]+1));
return 0;
}
[root@promote share]# ./a.out
数组a中的值为:1 2 3 4 5
a =0xbfa011e8, a地址上的值为:1
&a =0xbfa011e8, &a地址上的值为:-1080028696 //%d输出地址的结果
&a[0] =0xbfa011e8, &a+1地址上的值为:1
三者加一后的变化:
a+1 =0xbfa011ec, a+1地址上的值为:2
&a+1 =0xbfa011fc, &a+1地址上的值为:-1080028676 //地址超过数组所占的空间(越界),
&a[0]+1 =0xbfa011ec, &a[0]+1地址上的值为:2
[root@promote share]#
&a与&a+1在地址上的数值差值为((-1080028696) - (-1080028676))20(不计正负),
正好等于数组个数(5)*数组类型大小(int型为4字节)= 5*4=20;
若一个int型指针ptr指向&a+1,即int* p = (int*)(&a+1)//需强制转换否则报错: 警告:从不兼容的指针类型初始化
printf("%d\n", *(ptr-1));------结果为输出5。
原因:指针ptr先是指向数组末尾后一位的地址,因ptr为int型指针,其+1是指指针ptr往前走四个字节的长度。
正好走到数组元素5的开头地址,计算机读取数据时,从ptr指向的位置开始读取长度为ptr指向类型大小的数据(int型)。