【C生万物】 指针和数组笔试题汇总 (下)

本文通过8道笔试题详细讲解了C语言中指针与数组的使用,包括指针的增减操作、数组地址的计算以及在不同数据类型间的转换。题目涵盖了从基础到复杂的各种情况,如一维数组、结构体、二维数组以及字符串指针的运用,有助于深入理解C语言的内存和地址概念。
摘要由CSDN通过智能技术生成

 欢迎来到 Claffic 的博客 💞💞💞                               👉 专栏:《C生万物 | 先来学C》👈

前言:

承接上文,继续进行指针和数组的练习。


目录

Part2:指针笔试题 

1.做题

笔试1

笔试2 

笔试3 

笔试4

笔试5

笔试6

笔试7

笔试8

2.总结


Part2:指针笔试题 

1.做题

均要求输出结果 

笔试1

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}

答案及解析: 

*(a + 1): a表示首元素地址,+1得到第二个元素地址,解引用后得到 2
*(ptr - 1): ptr记录了整个数组下一位的地址,-1后得到数组最后一个元素的地址,解引用后得到5

笔试2 

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p的值为0x00100000。 如下表表达式的值分别为多少?
//已知:结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

答案及解析: 

0x00100014
0x00100001
0x00100004
0x开头,表示十六进制
p + 0x1                    -- p是结构体指针,+1表示加一个结构体的大小(20) 
   0x00100000 
 + 0x00000014 
== 0x00100014

(unsigned long)p + 0x1)    -- p强转为无符号长整型,+1就是+1
   0x00100000 
 + 0x00000001 
== 0x00100001

(unsigned int*)p + 0x1)    -- p强转为整型指针,+1表示跳过一个整型
   0x00100000 
 + 0x00000004 
== 0x00100004

笔试3 

// 小端  x86环境
int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int *ptr1 = (int *)(&a + 1);
    int *ptr2 = (int *)((int)a + 1);
    printf( "%x,%x", ptr1[-1], *ptr2);
    return 0;
}

答案及解析: 

%x 表示以十六进制打印
0x4
0x02000000
int *ptr1 = (int *)(&a + 1);
ptr1[-1]: 即*(ptr1 - 1),&a + 1表示整个数组的下一个位置,强转为整型指针后-1,表示向前跳过一个整型,即数组最后一个元素
int *ptr2 = (int *)((int)a + 1);
*ptr2:

笔试4

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p = a[0];
	printf("%d", p[0]);
	return 0;
}

答案及解析: 

注意逗号表达式,括号内取最后一个值
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
即{1,3,5}
理解: 
 1  3
 5  0
 0  0
a[0] 表示1的地址
p[0] 相当于*(p+0),即1

笔试5

int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

答案及解析: 

a 是二维数组名,p 是数组指针

p 与 a 指向的首元素相同

下图解释了两者的意义:

由此可以计算出 &p[4][2] - &a[4][2] 的值为 -4 ,按照整型打印就是 -4

按照地址打印,先要看 -4 在内存中是如何存储的:

即 -4 的补码形式:

11111111 11111111 11111111 11111100

换算为十六进制

FFFFFFFC

笔试6

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

答案及解析: 

1 2 3 4 5
6 7 8 9 10

int* ptr1 = (int*)(&aa + 1);    即10的下一个位置的地址
int* ptr2 = (int*)(*(aa + 1));  aa+1表示第二行的地址,解引用得到第二行数组
*(ptr1 - 1)        向前跳过一个整型,即二维数组的最后一个元素10
*(ptr2 - 1)        第二行数组向前跳过一个整型,得到第一行数组的最后一个元素5

 

笔试7

int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

答案及解析: 

 

a 是一个存贮字符指针的数组,里面有三个元素,分别指向三个字符串的首字母;

pa 是指针,它指向的数据类型是字符指针;

pa 指向第一个元素 char* a[0];

pa++,跳转到char* a[1],解引用就得到了字符串 at

笔试8

int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

 

答案及解析: 

 

这是原始状态:

**++cpp:

优先级 ** < ++

cpp++,指向空间c+2 ,一次解引用后得到空间 c+2 ,再次解引用得到 char*[2],指向P,打印出POINT;(cpp已被改变,指向空间c+2)

*-- * ++cpp + 3

先自cpp向左操作,最后+3

cpp++,此时已指向空间c + 1 ,解引用后得到空间c+1,此时--,即空间c+1--,得到空间c,解引用后得到ENTER中第一个E的地址,最后+3,得到ENTER中第二个E的地址,打印出ER;(cpp又被改变,指向空间c + 1 )

*cpp[-2] + 3  即 **(cpp-2) + 3

cpp++,指向空间c + 3,两次解引用得到FIRST中的F的地址,+3,得到其中S的地址,打印出ST; (cpp又被改变,指向空间c + 3 )

cpp[-1][-1] + 1   即 *(*(cpp-1)-1) + 1

cpp-1后解引用,得到空间c+2,-1得到空间c+1,解引用得到NEW中N的地址,+1得到E的地址,打印出EW。 

2.总结

指针+1表示跳过一个类型大小

如:整型指针+1,表示跳过一个整型的大小

一维数组名 a

a表示首元素地址,+1表示第二个元素的地址

&a表示整个数组的地址,+1表示数组末端的地址(数组外)

二维数组名aa

aa表示二维数组中一行数组的地址,+1跳过一行

aa[i] 表示二维数组中第 i 行的地址,+1跳过一行

&aa表示整个二维数组的地址,+1表示二维数组的末端(数组外)

%s传递字符地址,从当前字符开始,打印到 \0 结束 


总结: 

带你做了8道笔试题,有梯度,会第8道,这一部分就掌握的很好了。

码文不易 

如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦  💗💗

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Claffic

赏包辣条~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值