C语言中的 &和 *,以及数组名的本质,你理解吗?

根据大学中传授的知识,&叫做取地址,*叫做取内容。但是这种说法并不准确,也并不全面。

正确说法是:&叫作引用(reference),*叫作解引用(dereference),两者互为逆运算。

先举几个例子:

//大学中学到的取地址和取内容
int a = 10;
int * pa = &a;//此*仅仅是用于定义/声明指针变量用;&可理解为取地址
printf("a = %d\n",a);
printf("*pa = %d\n",*pa);//此*可理解为取内容
//一维数组中
int arr[5] = {1,2,3,4,5};
int * pArr = arr;
int * qArr = &arr[0];
//pArr和qArr两者是等价的
for(int i=0;i<sizeof(arr)/sizeof(int));i++)//这里写i<5就太low了
{
    //以下几种写法都是正确的,可以自行测试验证

    printf("%d\t",arr[i]);
    //printf("%d\t",pArr[i]);
    //printf("%d\t",qArr[i]);

    //printf("%d\t",*(arr+i));
    //printf("%d\t",*(pArr+i));
    //printf("%d\t",*(qArr+i));

    //printf("%d\t",i[arr]);
    //printf("%d\t",i[pArr]);
    //printf("%d\t",i[qArr]);
}
//本例中用到的&和*仍然可以理解为取地址和取内容,但是这种说法并不准确
//二维数组中
int arr[][4] = {{1,2,3,4},
                 {5,6,7,8},
                 {9,10,11,12}};//二维数组定义时,行数可以省,但列数不能省。
//下面两个都是大学至今玩坏的写法了,不再论述
//int * pArr = arr;
//int * qArr = &arr[0][0];

for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)//外循环,行
{
    for(int j=0;j<4;j++)
        {
            //下面三种说法等价
            //printf("%d\t",arr[i][j]);
            //printf("%d\t",*(arr+i)[j]);
            printf("%d\t",*(*(arr+i)+j));
            //第一个*还可以理解为取内容,但是第二个*再理解为取内容就说不过去了
        }
    putchar(10);
}

printf("%d\t",*(*(arr+i)+j)); 曾经有人说 & 和 * 是升维和降维,在某种程度上可以这样理解,但这种说法也不准确。

正确说法是:&叫作引用(reference),*叫作解引用(dereference),两者互为逆运算。&和*并不是单纯的实现取地址和取内容,而是实现了一级指针和数组指针之间的转换。当然有个前提,这里的一级指针是一维数组名,单纯的int a = 10; int * p = &a; 这种不包括在内。

首先数组名一定是地址,无论是几维的。一维数组的数组名本质是一级指针,二维数组的数组名本质是数组指针(上一篇文章已经简单论述过数组指针)。对一级指针(一维数组名)引用(&)一下得到数组指针(二维数组名),对数组指针(二维数组名)解引用(*)一下便得到一级指针(一维数组名)。由此可见两者确实是互逆运算。结合上面二维数组的例子也许能好理解一点。

另外,数组名是数组的唯一标识符,对于数组是很重要的标志。数组名也具有二义性,一是作为一种构造类型,表示数组这个整体;二是作为首元素地址访问数据成员。其中一维数组名作首元素地址访问成员时就是一级指针,如一维数组名+1(偏移一个单位长度),加的是4个字节(假设成员为int型)。而二维数组名作为数组指针,+1加的是一个数组大小。

最后补充一点,数组名下标运算的本质是基址偏移,如a[n]等价于*(a+n),a[m][n]等价于*(*(a+m)+n)。

PS:不知道自己论述的是否合格?C语言中的任何一个知识点都算得上是博大精深的,自己作为新手,只有一知半解,论述的不够全面。希望能跟更多喜爱C/C++的同学交流!

发布了34 篇原创文章 · 获赞 22 · 访问量 7202

猜你喜欢

转载自blog.csdn.net/lizun7852/article/details/86675886