最近我做了一些指针数组笔试题,感觉地址和数组元素的关系非常的冗杂,所以我打算整理一下,这篇文章我会先做一些总结,后续的文章会将面试题一一奉上,那我们现在进入正文。
第一点,最基础的结论
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。
明白以上两种特殊情况,我们可以知道出第一,二点的内容,其他地方我们将数组名理解为首元素的地址,但是这其中又有区别,下面我们以二维数组为例:
#include <stdio.h>
int main()
{
//二维数组
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
return 0;
}
在此,我们先讨论第三中情况(除此之外数组名表示首元素的地址),其他的内容请见下篇文章。
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0][0]+1));
printf("%d\n",sizeof(a[0]+1));
前三种情况,代表的都是二维数组首元素的地址,但又在地址的范围上有所区别:
a+1则表示跳过这个二维数组第一行首元素地址之后的地址,即第二行首元素的地址;
a[0]+1表示跳过这个二维数组第一行之后的地址,即第二行的地址;
a[0][0]表示跳过第一行第一个元素的地址,即第二个元素的地址;
那么将这三个结论与上面三个结论结合起来,我们应对这种类型题也就有迹可循了。
那么我们就来尝试一下这些结论:
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//中间是用逗号表达式,从左到右,输出为最后一个值
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
在这里有一个三行两列二维数组,且初始化部分是用逗号表达式,故只有三个元素;
创建一个指针变量p;
将a[0]的地址放到指针变量p里面,这时候a[0]表示的是第一行第一个元素的地址,幅度是一行;
那么输出p[0],p[0]等价于*(p+0),即*p,又考虑到指针变量p的类型是int*,所以解引用之后,
我们得到第一行第一个元素。
那么说到这里就有一个问题:这不是没啥区别吗?
那么我将代码改一下:
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };//中间是用逗号表达式,从左到右,输出为最后一个值
int* p;
p = a[1];
printf("%d", p[0]);
return 0;
}
将a[0] -> a[1],如果没有以上的对于地址幅度的理解,我们可以会得出答案是:3
但实际上,答案是:5
以上是我今天的分享,谢谢你们的观看。