数组名和指针到底是个啥关系?

这篇博客是我自己对数组名和指针的关系的理解,或许有的地方你会产生疑问,比如我认为数组名和指针是完全不同的,但是不要着急,保持怀疑请继续读下去,看你能不能和我产生一样的感觉…

一:数组名和指针属性不同

不要试图轻易的就给数组名和指针划上等号,他们之间总是会找到不同的,数组名就是数组名,是数组的首地址,是一个常量,不能进行++或者–等运算,而指针我们叫做指针变量,可以进行++,–,主要是在编译的时候,数组名和指针在编译器看来,他们的属性是完全不一样的,这就是两个东西,这是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是不一样的,这是数组名退化成了指针.

我的理解就写到这吧,至于别的不同,凯哥的这篇博客更详细,点这里.

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted on 2015-10-19 19:49  杨博东的博客  阅读(511)  评论(0编辑  收藏  举报

导航