C指针题目讲解

本文详细探讨了C++中指针与数组的相关知识点,包括指针指向数组后的偏移计算、结构体指针的增减操作以及数组在内存中的布局。通过实例分析了指针加减运算的原理,并解释了逗号表达式在数组初始化中的应用。此外,还讲解了多维数组、字符串指针及指针数组的用法,帮助读者深入理解C++的内存管理和指针操作。
摘要由CSDN通过智能技术生成

目录

 题目一:

 题目二:

 题目三:

 题目四:

 题目五:

 题目六:

 题目七:

 题目八:

 第一问:

 第二问:

 第三问:

 第四问:


题目一:

int main()
{
	int a[5] = { 1,2,3,4,5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}

这道题目的结果是什么呢?

这道题目不难分析。我们需要注意的是只有在&sizeof(只有数组名)的时候是整个数组,其余时候数组名一般都表示首元素地址

所以这里&a的类型是int(*)[5],数组指针再加一跳过了整个数组所以是不存在的a[5]的地址,又因为这时的类型是int(*)[5],不是int*,所以需要强制类型转换再赋予ptr.所以,*(a+1)就是a[1],也就是2.*(ptr-1)就是a[4],也即是5.

题目二:

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p=(struct Test*)0x100000;
//假设p 的值为0x100000.如下表表达式的值分别为多少?
//已知,结构体Test类型变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);//跳过一个结构体大小 
	//0x100000+20-->0x100014
	printf("%p\n", (unsigned long)p + 0x1);
	//转换成无符号长整型,1,048,576+1-->1,048,577
	//0x100001
	printf("%p\n", (unsigned int*)p + 0x1);
	//跳过4个字节  0x100000+4-->0x100004
	return 0;
}

这道题目我们需要注意的是,对于一个类型加一减一就是加上或减去它本身类型的大小,这一点在指针里面尤其重要.所以可以分析一下

 

 p的地址是0x100000加20就是0x100014.

 p的地址转换成unsigned int 类型+1就是1,048,577再转化为16进制数,是0x100001.

 unsigned int*大小为4个字节,所以0x100000+4==0x100004.

所以答案显而易见:

 题目三:

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);//%x是16进制 
	return 0;
}

这道题目我认为是比较难的一个题目,大家可以思考下,答案是4,2000000。这个结果可能比较出人意料,但是我们要是仔细分析一下就会解得。这道题目需要我们对于数据在内存中的存储有比较深刻的理解。下面我就浅析一下:

 题目四:

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

这个题目粗看是很容易看成是3行两列的数组:

 然后p是第一行数组名,显而易见就是0.但是答案确是1.为什么呢?我们细看就会发现数组里面不是{}而是(),所以是逗号表达式,取最后一个。所以真实的排布应该是:

所以答案是1.

题目五:

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

这道题目也是颇难的。话不多说,开始分析:
首先我们画个图来理解一下在内存中的排布:

 这样清晰了不少。

 题目六:

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));//10,5
	return 0;
}

这个题目比较简单。直接分析

 题目七:
 

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

分析:

 题目八:

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指向了C+3,但是不是++和--,所以没有副作用,不会改变在第四问还是指向C。

 

 好了,本期的分享就到这里了,剑心谢谢各位停留浏览啦、、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值