C语言数组和指针笔试题(四)

目录

感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接

🐒🐒🐒个人主页

🥸🥸🥸C语言

🐿️🐿️🐿️C语言例题

🐣🐓🏀python

二维数组

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a));
3:printf("%d\n",sizeof(a[0][0]));
4:printf("%d\n",sizeof(a[0]));
5:printf("%d\n",sizeof(a[0]+1));
6:printf("%d\n",sizeof(*(a[0]+1)));
7:printf("%d\n",sizeof(a+1));
8:printf("%d\n",sizeof(*(a+1)));
9:printf("%d\n",sizeof(&a[0]+1));
10:printf("%d\n",sizeof(*(&a[0]+1)));
11:printf("%d\n",sizeof(*a));
12:printf("%d\n",sizeof(a[3]));

在做之前我们再来复习一下数组名的意义
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址

例题一

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a));

*这里的a是整个数组,所以sizeof会计算整个数组的内存大小,因此结果就是(3*4)(数组的元素)4(整形类型的大小)=48

例题二

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a[0][0]));

这里的a00是指的数组首元素,因为是特别指定的一个元素,所以只需要计算整个元素的内存大小即可,因此a00是一个整形类型的元素,结果就是4

例题三

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a[0]));

a0是表示的第一行的数组元素地址,为了方便理解,我们暂时将数组中的元素改变一下,调试结果如图

*显然这里的a0是指的数组第一行地址,而不是第一列,第一行元素有4个,因此结果应该是4(第一行元素)4(整形类型的大小)=16

另外这里顺便补充一下

我们可以将二维数组表示成这样

但实际上二维数组的存储方式和上图是有一些区别的

这是每一行的地址,我们再来看一下每个元素的地址

这是每一行的每一个元素,地址的表示方式是16进制,因此我们可以看出每一个元素的地址相差为4个字节,第二行的首元素和第一行末尾的元素地址相差也是4个字节,因此我们可以推断出,二维数组的存储是下一行首元素地址接在上一行末尾元素的地址上 ,存储方式如图

例题四

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a[0]+1));

这里可能会有人非常纠结,a0+1是直接跳过第一行,还是直接跳过第一行的第一个元素,我们来看看调试的结果

a0+1是跳过第一行第一个元素,但是我们可以看到单独的a0却表示的整个第一行元素的地址,这是为什么呢?

其实二维数组我们可以这样写(下面的元素是为了方便理解所以改的 )

a34={{1,2,3,4},{5,6,7,8},{9,10,11,12}},这有点类似于数学中的换元

这里我们将二维数组看成一维数组,将二维数组存储的每一行元素地址 整体看成一个元素(二维数组是通过地址找到具体每一个元素),{1,2,3,4}就相当于换元中的t ,而要换的元素就是1,2,3,4

因此a0就是换元之后的第一个元素 ({1,2,3,4} ),a0={1,2,3,4}(是地址 ),而a0+1就是在换元中跳过第一个元素,所以就是&a01,因为是地址所以最后的结果就是4或者8

例题五

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(*(a[0]+1)));

上一题已经说过了a0+1=&a01,解引用就是第一行第二个元素,结果就是4
这里我们可以看出a0+1是一个地址,所以我们可以推断二维数组存的是一位数组的地址,a3={b4,c4,d4,e4},这里的b,c,d,e分别是第一行第二行第三行第四行元素的数组名
也就是说如果a3={{1,2,3,4},{2,3,4,5},{3,4,5,6},{4,5,6,7}}
那么 b4={1,2,3,4} c4={2,3,4,5} d4={3,4,5,6} e4={4,5,6,7}

例题六

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a+1));

这里的a不是单独放在括号里的,所以这里的a表示数组首元素的地址,a+1=&a1,这里一维数组也是一样的,因为是地址所以结果是4或者8

例题七

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(*(a+1));

上一题已经说过了a+1=&a1,对第二行地址解引用,所以就是第二行元素,结果就是4*4=16

例题八

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(&a[0]+1));

将二维数组看成一维数组,因此&a0就是取二维数组第一行地址,&a0+1为第二行的地址,所以结果为4或者8,也可以用前面换元的思想去理解,
a34={{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},这里的a0是第一行的数组名,所以&a0就是取第一行的地址,+1就是跳过第一行,所以&a0+1=&a1,因为是一个地址,所以结果是4或者8

例题九

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(*(&a[0]+1)));

&a0+1=&a1,解引用之后就是第二行的4个元素结果就是4*4=16

例题十

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(*a));

这里的a因为不是单独放在括号里的(有个号),**所以这里的a就表示第一行元素,结果就是44=16**

例题十一

c 复制代码
1:int a[3][4] = {0};
2:printf("%d\n",sizeof(a[3]));

这里可能很多人都会认为数组越界了,然后报错(我也是这样想的),结果并没有,因为sizeof他并不会管你数组会不会越界,在计算a3的时候他已经根据二维数组中的每一行会有多少个元素就确定a3中需要放入4个整形元素(因为每一行都是需要放入4个整形元素),所以结果是4*4=16

结果

总之二维数组要深入理解就太痛苦了,这几道题我想了好久,现在都没完全理解清楚,太难受了

相关推荐
泡海椒20 分钟前
JQuick-Excel 项目定位与适用场景:声明式 Java Excel 的边界
java·开发语言·excel
AC赳赳老秦23 分钟前
财报附注表格精准提取:OpenClaw 从 PDF 年报附注挖掘隐藏明细,补齐财务分析维度
java·汇编·c++·python·青少年编程·deepseek·openclaw
欧特克_Glodon26 分钟前
OpenCV计算机视觉开发入门与实践(基于C++):专栏内容介绍及目录
c++·人工智能·opencv·计算机视觉
箓维29 分钟前
线程的优缺点,与进程的关联和差异
java·服务器·笔记
slandarer36 分钟前
MATLAB | R2026b 更新了哪些有趣的新东西
开发语言·数据库·matlab
江屿风40 分钟前
【Linux系统】【从【收尾】缓冲区到【新开】磁盘块:一节课打通文件系统底层原理】流食般投喂
linux·运维·服务器·人工智能·笔记
李游Leo1 小时前
HarmonyOS 7 + ArkUI + Adaptive Layout 学习笔记:折叠屏多形态布局适配与窗口状态响应机制【鸿蒙心迹】
笔记·学习·harmonyos
工具派1 小时前
Word文档太大怎么拆分?段落结构与两种拆法的边界实测
开发语言·c#·word
码匠许师傅1 小时前
【C++三方组件】Asio 下篇:C++20 协程版 TCP 客户端与服务端
c++·tcp/ip·c++20
路漫漫其修远兮sjw1 小时前
Linux 运维知识点笔记(中级)
linux·运维·笔记