数组名和指针到底是个啥关系?
这篇博客是我自己对数组名和指针的关系的理解,或许有的地方你会产生疑问,比如我认为数组名和指针是完全不同的,但是不要着急,保持怀疑请继续读下去,看你能不能和我产生一样的感觉…
一:数组名和指针属性不同
不要试图轻易的就给数组名和指针划上等号,他们之间总是会找到不同的,数组名就是数组名,是数组的首地址,是一个常量,不能进行++或者–等运算,而指针我们叫做指针变量,可以进行++,–,主要是在编译的时候,数组名和指针在编译器看来,他们的属性是完全不一样的,这就是两个东西,这是C语言在设计数组的时候就是这么设计的,我们可以叫做”规定”.至于为什么这么设计,可能就是为了方便,我们本来可以用 “&a[0]”来表示的,但是直接用a不是更简单吗?
二:内部怎么区分它们?
我们都知道,*addr表示内存中(addr)的位置存储的值,比如*0x3a2b6532就表示地址为0x3a2b6532的内存中所存储的值。所以a[i]就表示a的值加上i所得到的数作为一个内存地址里面所存储的值.例如*0x3a2b6532就表示a的值,那么实际上a[1]就是*(0x3a2b6532+1)所表示的值,至于为什么要这样处理,原因就是指针偏移量是底层硬件所使用的基本模型。
三:代码见分晓
1:数组名的特殊性:
#include<stdio.h>
int main()
{
int a = 5;
int b[5];
int *p = &a;
printf("p的地址:%p &p的地址:%p\n",p,&p);
printf("b的地址:%p &b的地址:%p &b[0]的地址:%p\n",b,&b,&b[0]);
return 0;
}
我们可以看到,”p”和”&p”是不同的,但是”b”和”&b”以及”&b[0]”都是一样的,原因就在于”p”是一个指针,是一个变量,它里面保存的是它指向元素的地址,我们通过对它的操作可以改变指向元素的值,但是注意”&p”是p本身的地址,当然一般情况下,不会让”&p”的值等于”p”的值,因为这样的意思就是p指向p,即*(&p),我们取出p的地址再让它做指向运算,是没有意义的.再说b,前面已经强调过,b是一个常量,它的值就是我们的”&a[0]”,即它指向我们数组首元素,C语言就”规定”了数组名的特殊性,即a和&a[0]是一样,可能是由于我们的a[0] = *(a+0) 所以 &a[0] = &(*(a+0) = a,这种操作方式决定的.我们可以把a看做一种类型,叫做数组类型,它的特点就是本身和&是一样的地址,但是在作为函数传参的时候,它就会被退化成指针.再来一段代码:
#include<stdio.h>
void foo(int [][3]);
void foo(int b[][3])
{
printf("b:%p &b:%p\n",b,&b);
b++;
printf("b:%p\n",b);
b[1][1] = 9;
}
int main()
{
int i,j;
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
for(i = 0;i < 3;i++)
for(j = 0;j < 3;j++)
{
printf("a[%d][%d]:%p %d\n",i,j,&a[i][j],a[i][j]);
}
printf("a:%p\n",&a);
foo(a);
printf("%d\n",a[2][1]);
return 0;
}
可以看出传到foo函数的数组名,我们再次输出b和&b是不一样的,这是数组名退化成了指针.
我的理解就写到这吧,至于别的不同,凯哥的这篇博客更详细,点这里.
版权声明:本文为博主原创文章,未经博主允许不得转载。