8道指针进阶题,不小心,全是坑.

目录

前言

一、题目一

二、题目二

三、题目三

四、题目四

五、题目五

六、题目六

七、题目七

八、题目八

总结


前言

8道指针进阶题目,笔试会考,原题不一定,思路一定

一.理解大端存储和小端存储的概念. 1).大端存储:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放。. 2).小端存储:小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

指针相减按照%d输出为中间元素的个数.

一、题目一

#define _CRT_SECURE_NO_WARNINGS 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;

}

解析:

*(a+1)就是数组第二个元素的地址

 (int*)(&a+1)将&a+1强制类型转换成int*,ptr为&a+1,由于进行强制类型转换,所以ptr-1只移动四个字节,ptr-1地址指向5的地址,故输出的答案为2,5

二、题目二

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//由于还没学习结构体,这里告知结构体的大小是20个字节
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);
     return 0;

}

0x1为十六进制的1,由于p为结构体指针所以p+0x1会跳过整个结构体,所以答案应该是0x100014

(unsigned long)p是将地址转换成了十六进制的数,那么(unsigned long)p+0x1的答案为0x100001

(unsigned int*)p是将结构体指针强制类型转换成无符号int指针(unsigned int*)p+0x1跳过4个字节所以答案为0x100004.

三、题目三

#define _CRT_SECURE_NO_WARNINGS 1
#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;
}

&a+1就是整个数组后一个的地址,(int*)(&a+1)将地址强制类型转换成int*赋值给ptr1,所以ptr[-1]就相当与*(ptr-1),就是4,所以按照十六进制答案为4.

a为数组首元素地址,(int)a将首元素地址转换成一个十六进制的数,(int)a+1所以就是数加一,(int*)((int)a+1)将数强制类型转换成int*变成了地址.

举个例子如果首元素的地址为0x100000那么转换成数的一十六进制表示为0x100000此时是数不是地址那么加一就变成了0x100001,在转换成地址的话那么ptr2的地址就为0x100001.

 所以答案为4,2000000

四、题目四

#define _CRT_SECURE_NO_WARNINGS 1
#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;
}

这道题要注意的数组初始化的形式,在大括号内为小括号,所以为逗号表达式所以该二维数组数据存储形式为

 所以a[0]为第一行的地址,p[0]为*(p+0),答案为1.

五、题目五

#define _CRT_SECURE_NO_WARNINGS 1
#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;
}

这道题主要注意的是(*p)[4]是数组指针,指向为4个元素的数组.

所以&p[4][2]的地址为第18个元素的地址,&a[4][2]的地址为第22个元素的地址,由于是指针相减所以得到的是中间元素的个数为-4

所以%d输出的就是-4

如果要按照%p输出-4的

源码:10000000000000000000000000000100

补码:10000000000000000000000000000101

反码:11111111111111111111111111111010

按照十六进制进行输出为0xFFFFFFFC

所以答案为FFFFFFFC,-4

六、题目六

#define _CRT_SECURE_NO_WARNINGS 1
#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;
}

&aa+1为整个数组后一位的地址(int*)(&aa+1)强制类型转换成int*,所以ptr1-1向后移动4个字节的地址*(ptr1-1)为10.

aa+1为数组第二行的地址*(aa+1)为第二行数组(int*)(*(aa+1))强制类型转换成int*,所以ptr2-1向后移动4个字节的地址*(ptr2-1)为5.

所以答案为10,5

这道题就考你数组名代表着什么,如果想了解更多可以看空间指针进阶笔试题目全解析

七、题目七

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

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

 

 所以答案为at

八、题目八

#define _CRT_SECURE_NO_WARNINGS 1
#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;
}

 

printf("%s\n", **++cpp);

++cpp指向c+2,**++cpp为c[2],即POINT首元素地址,所以打印出来的是POINT

  

printf("%s\n", *-- * ++cpp + 3);

++cpp指向c+1,*++cpp为c+1,--*++cpp为c,*--*++cpp为c[0]即ENTER的首地址*--*++cpp+3为ENTER数组中E的地址,所以答案为ER.

 

printf("%s\n", *cpp[-2] + 3);

cpp[-2]为*(cpp-2),所以*cpp[-2] + 3就可以写成**(cpp-2)+3,cpp-2地址指向c+3,*(cpp-2)就是c+3,**(cpp-2)为c[3]即FIRST数组的首地址,**(cpp-2)+3为数组FIRTST中S的地址所以答案为ST.

printf("%s\n", cpp[-1][-1] + 1);

cpp[-1][-1]可以写成*(*(cpp-1)-1),cpp-1为c+2的地址,*(cpp-1)为c+2,*(cpp-1)-1为c+1,*(*(cpp-1)-1)为c[1]即NEW的首元素的地址*(*(cpp-1)-1)+1为数组NEW中E的地址,所以答案为EW.


总结

指针进阶8道经典笔试讲解,让你对指针游刃有余.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

笔写落去

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

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

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

打赏作者

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

抵扣说明:

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

余额充值