指针面试题总结

这篇博客总结了指针在面试中的常见问题,包括指针加减运算、大小端存储、数组的内存布局以及指针和数组的相互操作。通过实例解析了不同类型的指针对数组元素的访问方式,并讨论了地址计算和数值存储的相关细节。
摘要由CSDN通过智能技术生成
#include<stdio.h>
#include<stdlib.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int*ptr = (int*)(&a + 1);
	printf("%d,%d\n", *(a + 1), *(ptr - 1));
	system("pause");
	return 0;
}

在这里插入图片描述
2.

{
	int Num;
	char *pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
int main()
{
	p = (struct Test*)0x100000;
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	printf("%p\n", (unsigned char*)p + 0x1);
	printf("%p\n", (unsigned char**)p + 0x1);
	system("pause");
	return 0;
}

首先p是四个字节可写为0x00100000, 加0x1相当于加0x01,指针加一有几个字节取决于指针的类型,因为结构体大小为20个字节,所以十六进制下0x00100014
无符号long相当于0x00100000+0x00 00 00 01
p的类型是指针无符号int*,相当于加四个字节0x00100000+0x00 00 00 04
p的类型是指针无符号char*,相当于加一个字节0x00100000+0x00 00 00 01
p的类型是指针无符号char**,放的是char*类型的地址,相当于加四个字节0x00100000+0x00 00 00 04
在这里插入图片描述
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);
	system("pause");
	return 0;
}

在这里插入图片描述
本题考到大小端,数组在内存当中的存储,下标是由低地址到高地址的存储
在这里插入图片描述
4.

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

p[0]可写为*(p+0),表示第0行数组首元素的地址再结引用,所以答案为1,数组为下图所画。
在这里插入图片描述
在这里插入图片描述
5.

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int a[5][5];
	int(*p)[4];
	p = (int(*)[4])a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	system("pause");
	return 0;
}

第一个打印地址,第二个打印差值.P[4][2]可写为*(*(p+4)+2)
在这里插入图片描述
由图可以看出相减为-4
-4原码1000 0000 0000 0000 0000 0000 0000 0100
反码1111 1111 1111 1111 1111 1111 1111 1011
补码1111 1111 1111 1111 1111 1111 1111 1100
所以应该存储为FF FF FF FC
在这里插入图片描述
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));
	system("pause");
	return 0;
}

(aa+1)aa表示数组名,数组名代表数组首元素的地址,加1代表加到第一行的地址,结引用表示这一行本身
所以减一,int*类型减四个字节,所以为5
在这里插入图片描述
7.

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

数组名代表元素首元素地址,pa代表&a[0],pa++加四个字节,现在保存的是地址,再结引用取到里面的内容
在这里插入图片描述
在这里插入图片描述
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);
	system("pause");
}

在这里插入图片描述
在这里插入图片描述
*cpp[-2]= *( *(cpp-2))
在这里插入图片描述
cpp[-1][-1]= * ( * (cpp-1)-1)
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值