c++ 指针内容学习

本文内容来源于b站 程序员老秦

首先开胃菜,看一道一维数组例题

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

×
比较笨的小伙伴(我)会认为数组a指向的是首位,&a取址也是指向的是数组的首位,那么&a+1就是第二位2,认为最终的结果是2,1。

a和取址&a指向的是首地址没错,但是对取址&a而言,无论a是几维数组,&a+1一定是整个数组的跨度(放在例题中指向的就是5后面的一个元素),所以最终的输出是2,5

再来一道三维数组的例题

#include<stdio.h>
int main()
{
	int a[2][2][3] = {{{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}}};
	int* ptr = (int*)(&a + 1);
	printf("%d,%d",*(int*)(a+1),*(ptr-1));
	return 0;
}

首先,对于&a而言,几维数组带来的影响不大,因为&a+1一定是整个数组的跨度,因此第二项输入同样是数组的最后一个值12。但是对于三维数组而言,a+1,降维后的二维指针*a+1,再次降维后的一维指针**a+1,他们这个加1的跨度是不一样的。
具体怎么去看呢:

  • a+1就相当于在a[2][2][3]的第一个2上做加法,他的跨度就是2×3=6。
  • *a+1就相当于在a[2][2][3]的第二个2上做加法,他的跨度就是3。
  • **a+1就相当于在最后一维做加法,跨度就是1。

因此,本例的输出为1+6=7和12。

升级一下难度,char*

#include<stdio.h>
int main()
{
	static const char* s[] = {"black","white","pink","violet"};
	const char** ptr[] = { s + 3, s + 2, s + 1, s }, ***p;
	p = ptr;
	++p;
	printf("%s", **p + 1);
	return 0;
}

首先,s是二级指针(数组+char*),s指代的black的地址。
ptr是三级指针(数组+char**),***p也是三级指针,做相等后,***p指代的是s+3的地址,做自加后,***p指代的是s+2的地址,即pink这一元素的地址。
(**p)是对(***p)指代的地址进行取值,取出来也是一个指针,指的是pink的第一个字母p,+1后指到第二个字母i,所以本例的输出是ink。

三维数组和二维数组指针的结合

#include<stdio.h>
int main()
{
	int a[3][4]={{1,2,3,4},{2,3,4,5},{3,4,5,6}};
	int b[3][4]={{10,11,12,13},{11,12,13,14},{12,13,14,15}};
	int(*aa[2])[4] = {a, b};
	int* p1[3] = {a[0], a[1], a[2]};
	int* p2[3] = {b[0], b[1], b[2]};
	int** pp[2] = {p1, p2};
	int*** p = pp;
	printf("%d\n",(*(*p+2))[1]);
	printf("%d\n",aa[1][2] - aa[1][0]);
}

首先,p是三级指针,pp也是三级指针,aa也是三级指针(*加两个框),p1,p2都是二级指针,所以*p指的就是p1对应的地址(也就是a对应的地址),*p+2指的就是a[2]对应的地址,*(*p+2)就是a[2],所以第一个printf就是a[2][1]=4。
aa是三级指针,aa[1][2]其实就是b[2]对应的地址,aa[1][0]就是b[0]对应的地址,是两个指针相减,因此结果是8。

赋值之后指针指向内容突变

#include<stdio.h>
int main()
{
	const char* ptr[] = {"Welcome","to","Beautiful","Edoyunnn"};
	const char** p = ptr + 1;
	ptr[0] = (*p++) + 2;
	ptr[1] = *(p + 1);
	ptr[2] = p[1] + 3;
	ptr[3] = p[0] + (ptr[2] - ptr[1]);
	printf("%s\n",ptr[0]);
	printf("%s\n",ptr[1]);
	printf("%s\n",ptr[2]);
	printf("%s\n",ptr[3]);
}

首先,二级指针ptr指向的是ptr[0]对应的地址(“Welcome”),二级指针p指向的是ptr[1]对应的地址(“to”),(*p++) + 2注意这里是后置++,所以相当于先执行*p + 2在对p自加,*p即“to”,加2后没有内容,所以第一个输出空。此时,p自加完成,p指向了ptr[2]对应的地址(“Beautiful”),*(p + 1)即取ptr[3]的内容,所以第二个输出“Edoyunnn”。p[1] + 3,也即是ptr[3]的内容右移三位,即“yunnn”。最后,ptr[2]-ptr[1]是两个指针相减,差应该为3(一个指向E,一个指向y)。p[0]是ptr[2],也就是此时的“yunnn”,+3后得到“nn”。

多级指针多维数组的指针偏移运算

#include<stdio.h>
const char* c[] = {"Welcome","to","Beautiful","Edoyun"};
const char** cp[] = {c+3, c+2, c+1, c};
const char*** cpp = cp;

int main()
{
	printf("%s\n",**++cpp);
	printf("%s\n",*-- *++ cpp + 3);
	printf("%s\n",*cpp[-2] + 3);
	printf("%s\n",cpp[-1][-1] + 1);
	printf("\n");
	return 0;
}

答案:
Beautiful
come
yun
o

留给读者自测用~如果有不懂的欢迎一起讨论,或者可以从本文开头超链接去原视频收听讲解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值