每个使用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。如下图所示
关于指针,指针的指针,解引用,就分析到这,有不对之处请轻拍。