C++ 指针和指针的指针深入理解

每个使用C or C++的同学,应该都会经历指针模糊的问题,取址符又是什么?指针和取址很容易混淆。

现在来看一小段代码,以我的个人角度来细说理清一下。

#include <iostream>

int main()
{
	int i = 1;
	int j = 2;
	int* ip = &i;
	int* jp = &j;
	int** ipp = &ip;

	printf("address of i:%p\r\n", &i);
	printf("==========================\r\n");
	printf("value of ip:%p\r\n", ip);
	printf("address of ip:%p\r\n", &ip);
	printf("content of ip:%d\r\n", *ip);
	printf("==========================\r\n");
	printf("value of ipp:%p\r\n", ipp);
	printf("address of ipp:%p\r\n", &ipp);
	printf("content of ip:%p\r\n", *ipp);
	printf("value of i:%d\r\n", **ipp);
	printf("==========================\r\n");
	*ipp = &j;
	printf("value of j:%d\r\n", **ipp);

	return 0;
}

运行结果:

address of i:0036FC3C
==========================
value of ip:0036FC3C
address of ip:0036FC24
content of ip:1
==========================
value of ipp:0036FC24
address of ipp:0036FC0C
content of ip:0036FC3C
value of i:1
==========================
value of j:2

写在前面,指针的写法有两种,就是*号放在哪里,是贴在类型后面,还是贴在变量名前。以前写法都是采用后者(很大一部分人会采用这种写法),为了容易理解,我贴在类型后面,好分析一点。

1. 从语法的角度来看看:

int i = 1;

int* p = &i;

我们可以认为int和int*是一种类型,int的名字叫整型,int*的名字就叫int*吧。

后面变量i和p,都是变量名,这样的话:i对应该的内容就是1,p对应的内容就是&i;

使用盒子(盒子里表示的是变量的内容)的表示就是:


变量和指针都有两个共同的语法,就是取值和取址。

取值:使用变量名即可取值

取址:使用到取址符,&,即可以把当前变量的地址取出来

例如:

取i的值:i, i的内容是1;取ip的值:ip,ip的值为i的地址

取i的地址:&i;取ip的地址:&ip


2. 普通变量与指针变量的区别在哪?个人认为是:指针变量可以通过语法来取得指针指向的地址上的内容

先看看int* ip = &i;

这里面包含了两个行为,但是我们可以有三个操作。

a. int* ip,申请一个盒子

b.把&i的内容填到盒子里

操作可以有:

a.取出盒子的地址, &ip;

b.取出盒子的内容, ip;

c.取出盒子的内容所指向的地址上的内容,*ip;这就是我们所说的解引用了。


ip的内容是i的地址,那么,*ip的意思是:把ip的内容读出来-实际是i的地址,然后把这个地址上的内容取出来,即为i的值。

我个人的建议是:把*和变量分开来理解,就会容易多了:

在声明的时候,把它归在类型里,int*, void*;

在操作的时候,把它理解成一个单独的行为:就是把int*这个变量上面的内容取出来,根据取出来的内容指向找到对应的值。


3.再来理解一下指针的指针(不要怕它,只是一个纸老虎)

既然我们认为了int*是一个类型,那我们也认为int**是一个类型就好了

int* 的意思是:我声明的这个盒子,里面存的是指针;

int** 的意思是:我声明的这个盒子,里面存的是指针,这个指针指向的盒子里面的内容也是一个指针(这是正常的情况,被乱修改的情况就忽略)


从上图可以看到:

i的地址是:0036FC3C

ip的地址是:0036FC24

按照上面说的分析方法来理解:

a. ipp是一个变量;

b. *ipp是解引用,一个星就解引用一次:把ipp上的内容(实际是地址)指向的地址上面的内容取出来,即为ip上面的内容:0036FC3C;

c. **ipp是解两次引用,第一步,如果*ipp一样,取出来的是0036FC3C;然后再把0036FC3C地址上的内容再取出来,即为i的值:1

这样就是我们一直所说的指针的指针,只要把每一个细节剖开理解,就会容易理解了。


3.最后看看,*ipp = &j

可能这个比较容易产生疑惑,这实际上是什么意思?

我们也点点拆开来看,*ipp指是ipp上面的内容(实际是地址)指向的地址上面的内容,然后用&j的地址所覆盖。

所以最后一句的打印是:**ipp的值为j的值,2。如下图所示



关于指针,指针的指针,解引用,就分析到这,有不对之处请轻拍。

发布了70 篇原创文章 · 获赞 48 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/fwb330198372/article/details/80676413