序言:
通过学习,我了解到数组名在大部分的情况下都是代表数组首元素的地址,只有在sizeof(数组名)和&数组名这两种情况下,数字名代表整个数组,这也就决定了数组名在使用的过程中,需要我们格外注意。本篇文章将通过三步走的方法,一步一步剖析数组名和指针之间的微妙关系。
第一步:数组名实例解析
(1)思考以下代码:
#include <stdio.h>
int main()
{
int a[] = {
1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
给自己几分钟时间,想想答案是什么。
|
|
|
好了,接下来,我将逐行分析。
printf("%d\n", sizeof(a));
前面也提到,sizeof(数组名)这里数组名就代表整个数组,sizeof()是测变量或者类型占内存空间大小,单位:字节,所以此代码输出为4*4=16字节;
printf("%d\n", sizeof(a + 0));
这行代码和上一行很类似,但是他不是sizeof(数组名)这种情况,所以这里的数组名就属于一般情况,即数组名就是数组首元素的地址,a+0就是a所代表的地址向后跳过0个int单元,仍然是地址,所以输出就为4或者8,本篇文章运行的背景是在32位机器下运行的,所以输出为4;
printf("%d\n", sizeof(*a));
同理,这行代码也不是sizeof(数组名)的情况,也是一样的思考逻辑:数组名就是数组首元素的地址,这里*a代表解引用a地址下的元素,即数字1,1是int类型的,所以这行代码的输出为4;
printf("%d\n", sizeof(a + 1));
这行代码和第二行代码属于同一种类型,a这里代表数组首元素的地址,a+1代表a所代表的地址向后跳过1个int单元,也仍然是地址,所以输出就为4。这一行的输出和第二行的输出相差一个int单元,即4字节,我们也知道一个内存单元即一个字节对应一个地址,所以这两行的输出结果就差4;
printf("%d\n", sizeof(a[1]));
这里的a[1]等效于*(a+1),所以就是第二个元素即:2,类型为:int,所以输出为4;
printf("%d\n", sizeof(&a));
这里就得注意了,&数组名,这里的数组名代表整个数组,但是仍然是地址,这个地址代表整个数组,其数值依旧等于a,不同的是两者的类型,鉴于是地址,所以输出为4;
printf("%d\n", sizeof(*&a));
这个代码就有意思了,⁎和&是两个互逆的操作符,因此以上代码相当于sizeof(a),也就是4⁎4=16;除此理解之外,还有一种理解,这种理解我觉得是很有道理的:&a得到整个数组的地址,类型为:int (⁎)[4],在进行解引用操作时,得到的也将是整个数组,而整个数组占据的内存空间也为4*4=16;
printf("%d\n", sizeof