<笔试题>指针

目录

1、笔试题1:

2、笔试题2:

3、笔试题3:

4、笔试题4:

5、笔试题5:

6、笔试题6:

7、笔试题7:

8、笔试题8:


1、笔试题1:

#include<stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}
//程序的结果是什么?

  •  解析:

  • *(ptr - 1) :

&a表示取出整个数组的地址,&a+1就跳过整个数组,&a的类型:int(*)[5],&a+1的类型还是int(*)[5],将&a+1强制类型转换为int*,赋给ptr,则ptr指向的就是&a+1的地址,ptr-1即为前一个元素的地址,再解引用*(ptr-1)拿到的就是5。

  • *(a + 1):

a表示数组名为首元素1的地址,+1表示元素2的地址,再解引用*(a+1)就是2。

2、笔试题2:

#include<stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*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);

	printf("%x\n", p + 0x1);
	printf("%x\n", (unsigned long)p + 0x1);
	printf("%x\n", (unsigned int*)p + 0x1);

    //%p以地址的形式打印,不省略0
    //%x就是打印16进制,省略0
	return 0;
}

  • 解析:
  • p+0x1:

整形指针(int*)+1跳过4个字节,字符指针(char*)+1跳过1个字节,结构体指针p+1应该跳过一个结构体大小,也就是20字节,20的16进制是0x000014,加完后是0x100014。

  • (unsigned long)p + 0x1:

p本来是个结构体指针,把p强转成unsigned long类型,就是将变成无符号整型,就不再是指针了,既然是无符号整型,那就当成一个数字,加1后就直接加就行了,即0x100001

  • (unsigned int*)p + 0x1:

p被强制类型转换成整型指针,整型指针+1跳过4个字节,加4即为0x100004

3、笔试题3:

#include<stdio.h>
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;
}

  • 解析:
  •  ptr1[-1]:

&a取出的是数组的地址,&a+1跳过整个数组,将其强制类型转换为int*赋给ptr1,此时ptr1的地址就是&a+1,而ptr[-1]相当于*(ptr1-1),ptr1-1的地址如图所示,再解引用拿到的就是4。

  • *ptr2:

数组名a表示首元素地址,将其强制类型转化为整型,就是一个值,加1就是加了1个字节,需要将内存化为以字节为单位的数据,元素1就是4个字节,如果是小端,假设a的地址0x10,转成10进制就是16,加1就是17,16进制为0x11,找到ptr2的地址了,再解引用就只需再往后访问4个字节即可,打印出来即为2000000。过程如图所示

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

  •  解析:

此题有坑,考到了逗号表达式,int a[3][2] = { (0, 1), (2, 3), (4, 5) };这句代码可以转化为int a[3][2] = { 1, 2, 5 };此数组为3行2列,a[0]是第一行的数组名,数组名表示首元素地址,a[0]代表第一行第一个元素的地址,也就是p指向的位置,p[0] = *(p+0) = *p,p解引用拿到的就是1。

5、笔试题5:

#include<stdio.h>
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[4][2]:

&a[4][2]表示第5行第3列的地址,如图所示。

  • &p[4][2]:

 p是一个数组指针,p能够指向的数组是4个元素,p+1跳过4个整型,就是16个字节,p[4][2] --->*(*(p+4)+2),a是该数组数组名,即为首元素地址,将a赋给p,p也指向该地址,如图所示。p+1跳过4个元素的数组,+4的位置如图所示,*(p+4)向后找到4个元素,如黄色框框所示*(p+4),*(p+4)+2跳过2个元素指向的位置如图,再解引用,拿到的就是该元素。

  • &p[4][2] - &a[4][2]两个整型的地址相减拿到的就是中间的元素个数为4,因为小地址减大地址,所以%d的形式打印就是-4
  • 而%p的形式打印就是打印地址,只是打印补码即可

-4的补码:1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1100

换成16进制打印就是FFFF FFFF FFFF FFFC

6、笔试题6:

#include<stdio.h>
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;
}

  • 解析:
  • *(ptr1 - 1):

&aa表示二维数组的地址,&aa+1表示跳过整个二维数组到如图所示的位置,强转成整型指针赋给ptr1,ptr1-1的地址即如图所示,再解引用拿到的就是数字10。

  • *(ptr2 - 1):

aa为数组名表示二维数组首元素第一行的地址,aa+1跳过第一行来到第二行如图所示,再解引用*(aa+1)拿到第二行数组名首元素地址,即元素6的地址,强转赋给ptr2,ptr2-1向前移动再解引用拿到的就是5。

7、笔试题7:

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

  • 解析:

 pa的类型是char*,加1表示跳过了一个char*的元素,指向如图所示位置,再解引用*pa拿到a的地址,再%s向后访问到\0停止。即为at。

8、笔试题8:

#include<stdio.h>
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跳过了一个char**元素的地址到如图所示位置,解引用*++cpp拿到了c+2这个元素,c+2又是c里第3个元素的地址,再解引用拿到了p的地址,以%s的形式打印直到\0为止,即POINT。

  • *-- * ++cpp + 3:

++cpp再跳过一个char*的元素到图示位置,再解引用 * ++cpp拿到c+1,-- * ++cpp让c+1-1=c,此时c就是c数组名第一个元素地址,再解引用*-- * ++cpp拿到E的地址,再+3指向第二个E,再%s打印处ER。

  •  *cpp[-2] + 3:

  *cpp[-2]就是**(cpp-2)+3。cpp-2指向的位置如图所示,解引用*(cpp-2)拿到c+3,再解引用**(cpp-2)拿到F的地址,再+3指向S,再%s打印出ST。

  • cpp[-1][-1] + 1:

 cpp[-1][-1] + 1就是*(*(cpp-1)-1)+1,cpp-1的位置如图,解引用拿到c+2,减1就是c+1,再解引用*(*(cpp-1)-1)拿到的就是N的地址,再加1指向E,%s打印出EW。

评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

三分苦

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值