数组名结合指针的面试题的讲解

笔试题
第一题:

已知条件:
已知p为结构体指针变量,值为0x100000,并且结构体的大小为20字节,并且打印格式均为%p,%p不会在乎正负数,它会以补码的形式直接打印,0x1为16进制的1。
第一问:p+0x1,
p为结构体指针,指针的+1-1,是一种指针的关系运算,跳过的大小取决于指针本身的类型,如果是整形指针,它+1跳过四个字节,所以p+1会跳过20个字节大小,所以0x100000需要加上20个字节大小,但不是0x100020,要先把20转化为16进制,得到14,所以应该是00100014
第二问:它将16进制的0x100000强转成了无符号long 型,也就是强转成了整形,所以如果200+1就等于201,500+1就等于501,所以结果为00100001
第三问:它将p强转成了整形指针类型,这个时候+1-1,就应该是按照整形指针的权限来就是+-,所以应该是+4,结果为:00000004

第二题:

第一问:int *ptr1 = (int *)(&a + 1),

&a代表拿出了整个数组的地址,然后+1,此时指针会跳过整个数组,现在的类型是int * [4],它将其强转为了int *,然后问ptr1 [-1]是多少,ptr1 [-1]就是*(ptr+(-1)),就等与*(ptr-1),此时指针应该往回走1个单位,它是int*,所以往回走四个字节,刚好指向了4,所以结果为4。

vs是小端存储,所以从左往右存储数组的时候,是如图所示的存储方式。

第二问如图所示:int *ptr2 = (int *)((int)a + 1),

第一步:(int)a + 1,a为首元素地址,假设此时地址是0x0012ff40,现在被强转成了整数,然后对这个整数进行+1,结果就是0x0012ff41,然后又将这个整数强转成了int*的指针,此时的0x0012ff41就是一个新的地址了,它和原来的数组首地址0x0012ff40相比,它向后走了一个字节(如图ptr2所指向的位置),此时%x打印,应该向后访问四个字节的内容,由于是小端存储,所以数据应该是2000000

第三题:

问题:这是一个二维数组,3行四列,但是由于不是{ { },{ },{ }},而是{()()()},这是一个逗号表达式,保留下来的结果应该是1,3,5。所以这个二维数组应该如图所示:

然后 p = a[0];p是int*,这一步就是将a[0],也就是第一行的首地址赋给了p,所以p现在时第一行数组的首元素地址,然后p[0],也就是*p,所以直接打印出了1。

第四题:

如图所示:

第二问(%d)数组的存储是从低地址到高地址的,p指向的是一个4个整形的一维数组,p+1,p+2,p+3,p+4如图所示,每次跳过四个整形(16字节),所以p [4] [2]应该指向图中&p [4] [2]所对应的位置,此时和&a[4][2]进行相减,其结果的绝对值是中间相差的元素个数,因为以%d打印,所以应该是-4。

第一问(%p),是将-4以%p的形式打印,%p没有符号之分,直接将-4的补码以16进制进行打印

如图所示:-4的原返补码,以及16进制

第五题:

首先第一步char**pa = a; a是一个字符串数组的地址,这个地址被存放进了pa,类型是char**,

如图所示:

因为a是数组名,其代表首元素地址,也就是"work"的地址,然后pa++,它就跳过了首元素,指向了第二个元素,所以结果为 at

第六题:

第一问:*(ptr1 - 1)

首先:int *ptr1 = (int *)(&aa + 1);,这一步&aa取出了整个二维数组的地址,然后+1代表跳过了整个二维数组的地址,如图所示:

图中的红色ptr1就是跳过了二维数组指向的地址。然后此时把这个东西强转成了int*,它的类型从int(*)[2][5],变成了int*,然后以%d的形式打印*(ptr1-1),就是将红色的ptr1往后跳了四个自己,因为此时的红色ptr1是int*,解引用往后跳过4个字节,也就是一个整形的位置,所以指向了10。

第二问:*(ptr2 - 1)
首先* ( aa + 1 )这一步,aa为数组名,现在代表数组首元素地址,也就是一维数组1,2,3,4,5的首地址,然后+1.此时指向了第二个一维数组6,7,8,9,10的首地址,此时aa+1的类型是int(*)[5],然后就是对一个数组指针进行了解引用,所以结果是一个一维数组,然后又因为一维数组名代表首元素地址,也就是第一个元素6的地址,类型为int*,所以此时题目的将int*强转成int*是没有意义的,然后 * ( ptr2 - 1 )这一步,让ptr2往回走1个单位,因为ptr2是int*,所以它往回走四个字节,也就是一个整形的地址,指向了5的地址,所以结果是5。

第七题:

已知条件:

将3,4,5语句翻译如下图所示:

第一问 :printf("%s\n", **++cpp);

根据操作符得知从右往左读即可。

第一步:这是一个++cpp前置++,计算就是以++后的结果来计算的,cpp是一个三级指针,它存放的是二级指针数组的地址(cp的首地址),++让它由指向cp的首地址变成了指向cp中的第二个元素。

第二步:此时的一个*,对这个cpp指向的地址(也就是cp中的第二个元素的首地址)进行解引用,得到了cp中的第二个元素的内容c+2。

第三步:而c+2也是一个地址,它指向的是数组c中的第三个元素(如图),此时的最后一个*,对c+2这个地址进行解引用,得到了数组c中的第三个元素的内容,也就是字符串POINT的首地址,此时以%s形式打印,当然是得到POINT这个字符串啦。
第二问:printf("%s\n", *--*++cpp+3);
根据操作符的先后顺序,可知+3放在最后,其余的从右往左读即可。
\
第一步: ++ cpp,由于cpp在第一问的时候由于前置++指向了cp中的第二个元素,前置++的结果是在cpp上进行的,所以我们要保留第一问的操作,然后再进行前置++。此时cpp指向了cp中的第三个元素。
\
第二步:然后对cpp指向的数组cp中的第二个元素进行*的解引用 ,此时得到的是cp中的第三个元素的内容c+1。
\
第三步:对这个c+1进行前置--,即--(c+1),所以结果为c。
\
第四步:然后对c再次进行*,按照数组cp中元素c指向了数组c中的第一个元素,所以此时的结果是数组c中的第一个元素内容,也就是字符串ENTER的首地址。
\
第五步:此时最后一步+3,让这个地址让后移动3个单位,指向了ENTER中的第二个E的地址,再以%s的形式打印,也就是ER。
\
第三问:printf("%s\n", *cpp[-2]+3);
根据操作符的先后顺序,可知+3放在最后,其余的从右往左读即可。
\
第一步:cpp[-2],可以理解为*(cpp-2),由第二问可知cpp已经更新到了指向cp中的第三个元素的首地址,所以此时的cpp-2让指针往回走两个单位,指向了cp中的第一个元素的地址。此时cpp的移动不会影响到第四问cpp指向的元素,因为cpp-2的值没有赋给cpp,而++cpp这种是赋值了。
\
第二步:再进行*,得到了第一个元素的内容c+3,此时 * cpp [ - 2 ]的这一颗*,对c+3进行了解引用,得到了c+3所指向的数组c中的最后一个元素(FIRST的首地址),然后最后一步+3,与第二问类型,让指针指向了S的地址,再以%s打印,得到了ST。
\
第四问:printf("%s\n", cpp[-1][-1]+1);
根据操作符的先后顺序,可知+1放在最后,其余的从右往左读即可。
\
第一步: cpp [ - 1 ][ - 1 ]可以理解为 *(*(cpp-1)-1),由第三问可知,cpp还是指向了数组cp第三个元素的首地址,此时-1再*,得到的是c+2。
\
第二步:然后再对c+2进行-1再*,得到的是数组c中的第二个元素内容,也就是NEW的首地址,然后+1,与前面类似,指针指向了E的首地址,再以%s的形式打印,得到的是EW。

相关推荐
自由的dream33 分钟前
0-1背包问题
算法
2401_8572979139 分钟前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
良月澪二2 小时前
CSP-S 2021 T1廊桥分配
算法·图论
wangyue43 小时前
c# 线性回归和多项式拟合
算法
&梧桐树夏3 小时前
【算法系列-链表】删除链表的倒数第N个结点
数据结构·算法·链表
QuantumStack3 小时前
【C++ 真题】B2037 奇偶数判断
数据结构·c++·算法
今天好像不上班3 小时前
软件验证与确认实验二-单元测试
测试工具·算法
wclass-zhengge4 小时前
数据结构篇(绪论)
java·数据结构·算法
何事驚慌4 小时前
2024/10/5 数据结构打卡
java·数据结构·算法
结衣结衣.4 小时前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法