笔试题解析【指针和数组下篇】

笔试题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;
}
//程序的结果是什么?

分析:
1.(int *)(&a + 1):数组名a与&结合,取出的是数组的地址,+1跳过整个数组。所以ptr指向的是数组a末尾的地址
2.*(a+1):数组名a不是单独放在sizeof内部,也没有与&结合,所以此时数组名a是首元素的地址,*(a+1)是数组的第二个元素
3.*(ptr-1):ptr是指针,-1是指针减去4个字节的大小,所以*(ptr-1)是数组的最后一个元素。

图解:
在这里插入图片描述
运行结果:
在这里插入图片描述

笔试题2

题目:

struct Test
{
	int Num;//0-3
	char* pcName;//4-7
	short sDate;//8-9
	char cha[2];//10-11
	short sBa[4];//12-19
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体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;
}

分析:
1.p + 0x1:ptr的类型是struct Test ,结构体变量名p存放的是结构体的地址,+0x1跳过一个结构体的大小。0x100000+0x000014=0x100014。
2.(unsigned long)p + 0x1:将结构体变量名转换成unsigned long类型(无符号整型),+0x1就是就是在值上加1,0x100000+0x000001=0x100001。
3.(unsigned int*)p+0x1:将结构体变量p转化成无符号整型指针,+0x1就是跳过一个无符号整型指针的大小-4个字节,0x100000+0x000004=0x100004。

笔试题3

题目:

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);
	//%p - 打印地址
	//%x - 以十六进制的格式打印
	return 0;
}

分析:
1.int *ptr1 = (int *)(&a+1):数组名a与&结合,取出的是数组的地址+1跳过整个数组,所以ptr1存放的是数组末尾的地址
2.ptr[-1]:等价于*(ptr1-1),所以ptr[-1]就是数组最后一个元素的地址
3.int *ptr2 = (int *)((int)a + 1);将数组名a转换成整型,+1就是跳过一个字节大小

图解:
在这里插入图片描述
代码运行结果:
在这里插入图片描述

笔试题4

题目:

#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;
}

分析:
1.a[0]是数组首元素,将首元素的地址赋给p,p[0]等价于*(p+0)就是首元素。
2.(0, 1) 是逗号表达式,结果为最后一个","运算的结果,(0,1)的结果为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;
}

分析:
1.int a[5][5]:数组a是一个五行五列的二维数组。
2.int(*p)[4]:p的类型是数组指针。
3.p = a:将数组的首元素赋给p。
4.&p[4][2] - &a[4][2]:等价于*(*(p+4)+2) - *(*(a+4)+2);
5.这里大家可能有一个地方很疑惑,数组指针p只有4个元素,访问到了第五个元素,是不是越界访问了,回答是是的,但是它并没有改变该地址处的内容,是没有问题的,并且*(p+4)的类型依然是数组指针。

图解:
在这里插入图片描述
运行结果:
在这里插入图片描述

笔试题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.int *ptr1 = (int *)(&aa + 1): 数组名aa与&结合,取出的是数组的地址,+1跳过整个数组,所以&aa+1是数组末尾的地址。
2.int *ptr2 = (int )((aa + 1)): 数组名aa没有放在sizeof内部,也没有与&结合,所以aa+1就是第二行的地址,*(aa+1)就是数组第二行的元素。

图解:
在这里插入图片描述
运行结果:
在这里插入图片描述

笔试题7

题目:

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

分析:
1.char *a[] = {“work”,“at”,“alibaba”}:字符指针数组a存放的是字符串首元素的地址。
2.char**pa = a;pa是二级指针,存放的是a的地址。

图解:
在这里插入图片描述
运行结果:
在这里插入图片描述

笔试题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;
}

分析:
1.char *c[] = {“ENTER”,“NEW”,“POINT”,“FIRST”};
字符指针数组c存放着字符串的首元素的地址。
2.char**cp[] = {c+3,c+2,c+1,c};
二级指针数组cp存放的是字符指针数组c的地址,存放的顺序分别是:c+3,c+2,c+1,c。
3.三级指针cpp存放的是二级指针数组cp的地址。
4.**++cpp
三级指针自增,cpp存放着二级指针数组cp第二个元素的位置,然后解引用,找到c+2,再解引用找到“POINT”。
5.*–*++cpp+3
三级指针cpp先自增,此时cpp指向二级指针数组cp第三个元素的位置,然后先解引用,找到c+1,(c+1)自减变成c,然后再解引用,找到“E”,+3找到“E”。
6.*cpp[-2]+3
cpp[-2]等价于*(cpp-2),三级指针cpp此时指向的是二级指针数组cp的第三个元素(此时cp第三个元素是c),-2找到c+3,再解引用找到“F”,+3找到“S”。
7.cpp[-1][-1]+1)
cpp[-1][-1]等价于*(*(cpp-1)-1),三级指针cpp此时指向的是二级指针数组cp的第三个元素(此时cp第三个元素是c),-1找到c+2,再-1找到c+1,解引用找到“N”,+1找到"E"。

图解:
在这里插入图片描述
运行结果:
在这里插入图片描述


结语:

感谢大家看到这里,如有错误,希望各位大佬多多指正!
祝大家心情愉悦!
在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值