【C语言进阶】指针笔试题详解(真的超详细!)

【C语言进阶】指针笔试题详解(真的超详细!)


十、指针笔试题

1 笔试题1

代码示例

#include<stdio.h>

int main()
{
	//笔试题1

	int arr[5] = { 1,2,3,4,5 };
	int* ptr = (int*)(&arr + 1);

	printf("%d, %d\n", *(arr + 1), *(ptr - 1));
    //打印结果:2, 5 

	return 0;
}

解释说明

1 (int*)(&arr + 1)

  &arr 表示整个数组的地址,+1表示向后跳过一个数组类型的地址( int(*)[4]

  &arr+1 即为数组末尾元素 5 后一个位置的地址

  将该地址强制类型转换为 int* 后赋给指针变量 ptr

2 *(arr + 1)

  arr+1 表示 &arr[1]*(arr + 1) 表示 arr[1]

图示说明

笔试题1

2 笔试题2

代码示例

#include<stdio.h>

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = 0x100000;	//假设指针变量p的值为0x100000
int main()
{
	//笔试题2
	//已知结构体类型的变量大小为20个字节(0x14)

	printf("%p\n", p + 0x1);
	//地址+1,跳过一个结构体类型的地址
	//地址计算:地址+1 --> 0x100000 + 0x14 = 0x00100014
	printf("%p\n", (unsigned long)p + 0x1);
	//值+1,十六进制整数+1
	//十六进制整数计算:0x100000 + 0x1 = 0x00100001
	printf("%p\n", (unsigned int*)p + 0x1);
	//地址+1,跳过一个整型地址
	//地址计算:地址+1 --> 0x100000 + 0x4 = 0x00100004

	/*
	* 打印结果:
	*	00100014
	*	00100001
	*	00100004	
	*/

	return 0;
}

解释说明

1 p + 0x1

  表示结构体指针 p ( struct Test* 类型)的值+1,也就是地址+1p 类型的大小为20个字节( 整数20的十六进制形式:0x14 )

  地址+1后的值为:p的值(地址) + 0x14

//0x100000 + 0x14 = 0x00100014

2 (unsigned long)p + 0x1

  指针变量 p 的值被强转为了一个 unsigned long 类型的值

​  即: 一个十六进制的整数 + 0x1

//0x100000 + 0x1 = 0x00100001

3 (unsigned int*)p + 0x1)

  指针变量 p 的类型被强转为 (unsigned int*) 类型,还是一个地址,地址+1

  新的类型大小为4个字节( 整数4的十六进制形式:0x4 )

​  地址+1后的值为:p的值(地址)+ 0x4

//0x100000 + 0x4 = 0x00100004


3 笔试题3

代码示例

#include<stdio.h>

int main()
{
	//笔试题3

	int arr[4] = { 1,2,3,4 };
	int* ptr1 = (int*)(&arr + 1);
	int* ptr2 = (int*)((int)arr + 1);

	printf("%x, %x\n", ptr1[-1], *ptr2);//4, 2000000

	return 0;
}

解释说明

1 (int*)(&arr + 1)

  &arr 表示整个数组的地址,+1表示向后跳过一个数组类型的地址( int(*)[4]

  &arr+1 即为数组末尾元素 5 后一个位置的地址

  将该地址强制类型转换为 int* 后赋给指针变量 ptr1

2 (int*)((int)arr + 1)

arr  --  数组首元素的地址
(int)arr  --  将地址(int*类型的值)强制类型转换为int型的值
(int)arr+1  --  int型的值 +1  --  值可以看做是首元素的地址向后移动一个字节的地址
(int*)((int)arr+1)  --  将首元素的地址向后移动1个字节大小空间后的地址  --  原地址+0x1

3 %x 转换说明

​  表示以十六进制形式打印值

图示说明

1 ptr1

笔试题3(1)

2 ptr2

  该机器以小端字节序存储,取得的 int 型整数为:02000000(十六进制)

笔试题3(2)

4 笔试题4

代码示例

#include<stdio.h>

int main()
{
	//笔试题4

	int arr[3][2] = { {0,1},{2,3},{4,5} };
	int* p;
	p = arr[0];//二维数组的首元素,是一个一维数组的数组名

	//p[0] -> *p -> *(p+0) -> *arr[0] -> *(arr[0]+0) -> arr[0][0] -> 第一行第一个元素 -> 0
	printf("%d\n", p[0]);//0
	printf("%d\n", *arr[0]);
	printf("%d\n", arr[0][0]);
	printf("%d\n", *p);
	printf("%d\n", *(p + 0));
	printf("%d\n", *(arr[0] + 0));

	return 0;
}

解释说明

1 arr[0] 表示二维数组的首元素

  相当于一个一维数组数组名,一维数组名表示一维数组首元素的地址(&arr[0][0])。

2 p[0] 相当于是 *(p+0)

p[0] --> *(p+0) --> *(arr[0]+0) --> arr[0][0] --> 第一行第一个元素 --> 0


5 笔试题5

代码示例

#include<stdio.h>

int main()
{
	//笔试题5

	int arr[5][5];//二维数组
	int(*p)[4];//数组指针
	p = arr;
	//arr -> int(*)[5]
	//p   -> int(*)[4]

	printf("%p, %d\n", (&p[4][2] - &arr[4][2]), (&p[4][2] - &arr[4][2]));//FFFFFFFC, -4
	//&p[4][2] -> &(*(*(p+4)+2))

	return 0;
}

解释说明

1 arr二维数组数组名,表示二维数组首元素的地址,其类型是 int(*)[5]

2 &p[4][2] - &arr[4][2] 表示指针-指针|指针-指针|(绝对值)得到的是指针之间元素的个数

3 &p[4][2] - &arr[4][2] 计算结果是-4, %p 以十六进制形式打印输出,会将-4的补码当做地址打印

10000000 00000000 00000000 00000100 - -4的原码
11111111 11111111 11111111 11111011 - -4的反码
11111111 11111111 11111111 11111100 - -4的补码

//将-4的补码当做地址打印(将二进制补码转换成十六进制整数):
1111 1111 1111 1111 1111 1111 1111 1100
F    F    F    F    F    F    F    C
FF FF FF FC

图示说明

笔试题5

6 笔试题6

代码示例

#include<stdio.h>

int main()
{	
	//笔试题6

	int arr[2][5] = { {1,2,3,4,5},{6,7,8,9,10} };
	int* ptr1 = (int*)(&arr + 1);
	//&arr+1表示向后跳过一个二维数组类型的地址
	int* ptr2 = (int*)(*(arr + 1));
	//*(arr+1)表示arr[1],也就是二维数组第二行,表示一个一维数组名,即&arr[1][0]

	printf("%d, %d\n", *(ptr1 - 1), *(ptr2 - 1));//10, 5

	return 0;
}

解释说明

1 &arr + 1

  &arr 表示取出二维数组的地址&arr+1 表示跳过一个二维数组类型的地址

2 *(arr + 1)

​  arr+1 表示 &arr[1]*(arr+1) 表示 arr[1] ,即二维数组首元素,一个一维数组数组名,即 &arr[1][0]

*(arr+1) -> arr[1] -> &arr[1][0] -> 第二行第一列元素的地址 -> int*

图示说明

笔试题6

7 笔试题7

代码示例

#include<stdio.h>

int main()
{
	//笔试题7

	char* arr[] = { "work","at","alibaba" };
	char** pa = arr;//arr -> 指向字符'w'的字符指针变量的地址
	pa++;//p++ -> arr+1

	//*pa -> *(arr+1) -> arr[1] -> 字符'a'的地址
	printf("%s\n", *pa);//at

	return 0;
}

解释说明

1 arr字符指针数组数组名,表示数组首元素的地址,即指向字符 w 的字符指针变量的地址

2 pa++; 可以理解为 pa = arr+1;此时二级指针变量 pa 存放的是字符指针数组第二个元素的地址

3*pa

*pa -> *(arr+1) -> arr[1] -> 字符'a'的地址

图示说明

笔试题7

8 笔试题8

代码示例

#include<stdio.h>

int main()
{
	//笔试题8

	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** pc[] = { c + 3,c + 2,c + 1,c };
	char*** ppc = pc;

	printf("%s\n", **++ppc);		//POINT
	//++ppc -> pc+1 -> &pc[1]
	//*++ppc -> *(pc+1) -> pc[1] -> c+2
	//**++ppc -> *(c+2) -> 'P'的地址
	//此时ppc == pc+1
	//
	printf("%s\n", *-- * ++ppc + 3);//ER
	//++ppc -> pc+2 -> &pc[1]
	//*++ppc -> *(pc+2) -> pc[2] -> c+1
	//--*++ppc -> c -> &c[0] -- (此时pc[2]的值由c+1变成了c)
	//*--*++ppc -> *c -> c[0] -> 第一个'E'的地址
	//*--*++ppc+3 -> c[0]+3 -> 第二个'E'的地址
	//此时ppc == pc+2,pc[1] == c
	//
	printf("%s\n", *ppc[-2] + 3);	//ST
	//ppc[-2] -> *(ppc-2) -> *(pc+2 -2) -> *(pc) -> *(pc+0) -> pc[0] -> c+3 
	//*ppc[-2] -> *(c+3) -> c[3] -> 'F'的地址
	//*ppc[-2]+3 -> c[3]+3 -> 'S'的地址
	//
	printf("%s\n", ppc[-1][-1] + 1);//EW
	//ppc[-1] -> *(ppc-1) -> *(pc+2 -1) -> *(pc+1) -> pc[1] -> c+2
	//ppc[-1][-1] -> *(*(ppc-1)-1) -> *(c+2 -1) -> *(c+1) -> c[1] -> 'N'的地址
	//ppc[-1][-1]+1 -> c[1]+1 -> 'E'的地址
	//
 
	/*
	*	POINT
	*	ER
	*	ST
	*	EW
	*/

	return 0;
}

解释说明

1 指向关系图示

笔试题8

2 **++ppc

ppc --> pc+0 --> c+3 --> 'F'的地址(FIRST)
++ppc --> ppc+1 --> pc+1
*(++ppc) --> *(ppc+1) --> *(pc+1) --> c+2
**(++ppc) --> **(ppc+1) --> **(pc+1) --> *(c+2) --> 'P'的地址(POINT)

笔试题8(1)

3 *-- * ++ppc + 3

ppc --> pc+1 --> c+2 --> 'P'的地址(POINT)
++ppc -- > ppc+1 --> (pc+1)+1 --> pc+2
*(++ppc) --> *(pc+2) --> c+1
--(*(++ppc)) --> --(*(pc+2)) --> --(c+1) --> c
*(--(*(++ppc))) --> *(--(*(pc+2))) --> *(--(c+1)) --> *c  --> 'E'的地址(ENTER)
*(--(*(++ppc)))+3 --> 'E'的地址+3 --> 'E'的地址(ER)

笔试题8(2)

4 *ppc[-2] + 3

ppc --> pc+2 --> c+1 --> 'N'的地址(NEW)
*ppc[-2]+3 --> *(*(ppc-2)+3)
ppc[-2] --> *(ppc-2) --> *((pc+2)-2) --> *(pc+0) --> c+3
*ppc[-2] --> **pc --> *(c+3) --> 'F'的地址(FIRST)
*ppc[-2]+3 --> *(c+3)+3 --> 'F'的地址+3 --> 'S'的地址(ST)

5 ppc[-1][-1] + 1

ppc --> pc+2 --> c+1 --> 'N'的地址(NEW)
ppc[-1][-1]+1 --> *(*(ppc-1)-1)+1
ppc[-1] --> *(ppc-1) --> *((pc+2)-1) --> *(pc+1) --> c+2
ppc[-1][-1] --> *(*(pc+1)-1) --> *((c+2)-1) --> *(c+1) --> 'N'的地址(NEW)
ppc[-1][-1]+1 --> *(c+1)+1 --> 'N'的地址+1 --> 'E'的地址(EW)


总结:

  本节详细介绍了8道指针相关的笔试题,用详细的注释与示例图画对题目代码进行深度剖析。


感谢您的阅读!如有任何错误,欢迎您的批评指正!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值