【LeetCode大厂笔试题】之变态指针!

很多同学在学完指针后,弄懂了「*」和「&」的含义,又写了几个字符串相关的编程题,再刷几道指针笔试题,感觉指针精通了。其实C语言中的指针真是博大精深,他的复杂程度绝对超过你的想象。比如前两天一个同学来问我的问题,先看下代码:

#include <stdio.h>

int main()
{    
	const char *ptr[] = {"Welcome", "to", "Beautiful", "Nanjing"};
	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]);
    	
    	return 0; 
}

这是一个典型的指针笔试题。我见过大部分的同学做笔试题都擅长使用 「观察法」 ,如果这道题能用「观察法」得出结果,算我输!

代码就跟数学题一样,还是要动手算的。所以我们这篇文章就来详细的剖析一下。

STEP01

我们先来解决这行代码:

const char *ptr[] = {"Welcome", "to", "Beautiful", "Nanjing"};

很显然,定义了一个指针数组,对应的内存模型是这样的:

在这里插入图片描述
ptr是个数组,里面有4个指针,分别指向了内存里面的四个字符串。如果这个都没看懂的话…

在这里插入图片描述
那接下来就只能看个热闹了!

STEP02

下一行代码:

const char **p = ptr + 1;

这个就有点意思了,定义了一个指针的指针。首先要弄懂,「ptr + 1」是啥?ptr是数组的名字,也是数组的首地址,所以「ptr + 1」应该是数组第二个元素的地址,即0x2000的地址,看图:

在这里插入图片描述
所以,p的值就是0x104。至于说为什么p要定义成指针的指针,写成指针不行吗?还真不行,因为0x104这块内存里面保存的是一个地址,也就是说0x2000这个数据是「char *」类型。

STEP03

下面轮到几个赋值语句了,一行一行看:

ptr[0] = (*p++) + 2;

首先要搞懂「p++」。因为是后置++操作,先不管他。p指向数组第二个元素,那么p就是数组第二个元素,即0x2000。0x2000它是个指针,就是「char *」类型,步长是1个字节,所以加2结果是0x2002,也就是字符串“To”后面的那个字节,说白了就是字符’\0’。因为是个赋值语句,所以ptr[0]变成了0x2000。最后别忘了指针p向后加一。p指向数组第二个元素,加一的话指向了数组第三个元素,于是他们之间的关系变成了:

在这里插入图片描述
STEP04

继续:

ptr[1] = *(p + 1);

p现在的值是0x108,所以「p + 1」变成了0x10c,对这个地址取值,就是0x10c内存里面保存的数据0x1500,赋值给ptr[1],于是关系又变成了:

在这里插入图片描述

STEP05

再一次赋值:

ptr[2] = p[1] + 3;

p指向数组第三个元素,那么p[1]就是从第三个元素开始,向后数1个元素,就是数组的第四个元素,所以p[1]的数值应该是0x1500,0x1500是「char *」类型,步长一个字节。所以加3结果就是0x1503,不就是’j’的地址吗!

在这里插入图片描述

STEP06

最后一次赋值:

ptr[3] = p[0] + (ptr[2] - ptr[1]);

这条语句就比较「贱」了,明摆着故意刁难学生!p[0]就是指针p指向内存的值,即0x1503。「ptr[2] - ptr[1]」看起来太吓人了。ptr[2]就是0x1503,ptr[1]就是0x1500,这两个类型一样,都是 「char *」类型,步长为1,所以你就把它当作数字运算就行了,结果是3。因为p[0]也是「char *」类型,所以加3就变成了0x1506,就是字符’g’的地址。

在这里插入图片描述

STEP07

最后呢,就是把这些地址指向的内存数据打印出来,结果是:

在这里插入图片描述

分析就到这。最后要提醒大家:

1、不管多么复杂的指针运算,「观察法」解决不了问题(智商过140的除外!),还是要动手画图;
2、指针可以当作数组使用,数组也可以当作指针使用,单纯从使用的角度来看,指针和数组没有区别(注意,是使用的角度,不是说指针和数组一样没有区别);
3、不管是指针还是指针的指针,不要乱了阵脚,搞清楚它们的步长、性质。

更多文章、视频、嵌入式学习资料,微信关注公众号 『学益得智能硬件』

在这里插入图片描述

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页