const指针与指向const的指针:
const double * const pc = rates;
第二个const:pc是一个const指针(不能再指向别的变量)
第一个const:pc指向的东西是const double 类型,即rate的声明类型应该是const double
数组和指针:
int zippo[4][2];
zippo[0] zippo[0]+1
↓ ↓
zippo----> 0 1
zippo + 1----> 2 3
4 5
6 7
zippo[0]:一维数组名,在zippo[0]中存放的是zippo[0][0]的地址,所以它指向的是int
zippo:二维数组名,在zippo中存放的是zippo[0]的地址,但不能单纯形容zippo为指向[指向int 的指针]的指针,具体参见前面的博客:2021-01-16 关于c primer plus 10.7的思考(二维数组名不等同于二维指针)
简而言之,zippo[0]是一 个占用一个int大小对象的地址,而zippo是一个占用两个int大小对象的地址
类型讨论完了,来看看具体的值
zippo和zippo[0]显然都指向了同一块起始地址{尽管它们+1跳过的范围不同},所以它们的值是相等的,都是zippo[0][0]的地址
多重解引用的危险:
c中,不同类型不同维度的指针可以相互赋值
除此之外,一个指向非const的指针甚至也能被一个指向const的指针赋值
尽管这样做并没有什么意义,但其行为是未定义的,但不同的编译器也许会给出warnning或者error
即使你的编译器成功让一个指向非const的指针,指向了一个不被允许修改的值,当真的去修改时,其行为也是未定义的,编译器也许不会警告也不会报错
也许就此人们倾向认为:那么让指向const的指针,去指向一个非const的值,则是完全没有问题的
尽管c允许一个声明时指向const的指针,实际上能指向const的数值,也能指向非const的数值
但只有在一级解引用的情况下才是真正安全的
案例示范:
一个二级指针pp,它被声明const int* * pp;
一个一级指针p,它被声明为int * p;
一个变量,const int n = 100;
pp = &p; //pp指向p (const指向非const,被允许)
*pp = &n;//p指向了n //pp被声明为指向const int**,解引用后的结果被判断为const int*,于是n便可以赋值给*pp
*p = 0;//p被声明为非const,于是它指向的内容被修改,但是这里它实际指向了const类型
这种情况出现的主要原因是:const指向了非const,而在解引用后的操作中,只根据声明类型判断是否合法,而非追溯实际类型(天啊我有点想到Java的多态和动态链接)