预备知识:
1,变量:(有两个东西)
- 声明一个变量,系统给变量分配了一个存储单元,它是一个地址域和一个值域的统称。
2,普通变量和指针变量的区别:(值域有区别)
- 普通变量:值域中存放具体的数据
- 指针变量:值域中存放地址
3,赋值操作:(赋值就是覆盖值域!)
- 值域覆盖值域,即普通变量 a, b 相互赋值情况: a = b。这里是 a 的值域用 b 的值域进行覆盖,a 和 b 的地址域并没有进行操作!(这里补充一下指针变量 p1, p2 相互赋值的情况:p1 = p2。这里是 p1 的值域用 p2 的值域覆盖。)
- 地址域覆盖值域,即指针变量 p 和普通变量 var 相互赋值情况:p = &var。这里是 p 的值域用 var 的地址域进行覆盖。
代码:
int main(void){
int var=0;
int *p = NULL; // 一级指针
int **pp = NULL; // 二级指针
p = &var; // 一级指针保存 var 的地址
pp = &p; // 二级指针保存 p 的地址
printf("address of var: %d\n", &var);
printf("address of p: %d\n", &p);
printf("address of pp: %d\n", &pp);
printf("\n");
printf("value of p: %d\n", *p);
printf("value of pp: %d\n", *pp);
printf("value of p: %d\n", **pp);
return 0;
}
运行结果
整理结果:
地址域 | 值域 | |
var 的地址:1703716 | var 的值:3 | |
p 的地址:1703720 | p 的值:3 | |
pp 的地址:1703724 | pp 的一级取值:1703716 | pp 的二级取值:3 |
问题提出:
- 问题来了,基于对预备知识的理解,也就是 p 的值域应该存储 var 的地址域,而 pp 的一级值域应该存储 p 的地址域。然而,上述代码运行后,整理出来的结果中,p 的值域却是 var 的值域,pp 的一级值域却是 var 的地址域。
问题解决:(*p)的理解
(注意: 取出值域意思是下一级的指针域,连带值意思是下一级的指针域的值域)
-
首先明确预备知识是没有错的,代码运行结果也没有错,错的地方在于对 星号 * 的理解上
-
(*p)的意思是取出 p 的值域(也就是 var 的地址域)的连带值,该值就是 var 的值域 3 。
-
(*pp)的意思是取出 pp 的值域(也就是 p 的地址域)的连带值,该值就是 p 的值域,也就是 var 的地址域 1703716。
-
(**pp)等价于 (*(*pp)),意思是先进行 *pp 操作取出 p 的值域,然后再进行 (*p)操作取出 p 的值域的连带值。
-
总结星号 * 的意思是取出值域的连带值。这么理解有点儿绕,图示说明:
白色的是地址域,红色的是值域。以 p 为例,p 的下一级是 var,而 p 的值域保存的是 var 的地址域,var 的地址域连带值域就是 3。 -
【当然官方说法是 (*p )表示: p 指向地址的内容,简记:取内容。这么记忆我自己不好理解,记成:取值域连带值,还挺可以】
延申一个问题:
下面的代码第 8 行,为什么运行不正确?不是说 p 是指针变量,那么它的值域保存的就是地址吗?为什么取了一个 a 的地址给它,还不对了呢?
int main(void){
int *p = NULL;
int a[3] = {1, 2, 3};
p = &a; // 这里运行错误
return 0;
}
答案: 这里又体会到了,同级别赋值就是值域赋值,不同级别赋值就是低级别的指针域赋值给高级别的值域。基于这个理解,这里可以将第 8 行右边,降低级别为普通变量,改为:p = &a[0],成功运行。也可以将第 8 行左边升高一个级别,为二级指针变量,会发现失败。但是如果 a 不是数组指针,而是一个普通的指针,将左边升高一个级别的操作则是没问题的。如下代码:
int main(void){
int **p1 = NULL; // p1 升高一个级别,二级指针
int *p2 = NULL; // p2 为一级指针
p1 = &p2;
return 0;
}
这里就又抛出了一个问题
为什么数组指针的情况,将左边升为二级指针失败了呢?也就是如下代码:
int main(void){
int **p1 = NULL; // p1 升高一个级别,二级指针
int a[3] = {1, 2, 3}; // a 是一级指针
p1 = &a;
return 0;
}
答案:数组名的本质是 &a[0],而 &a 的意思是int *[] 类型。