①指针的本质:
int a = 1;
int *p = &a;
&a是一个地址,而把它赋给一个整型指针,说明指针本质和它相同,是一个地址,即指针等价于地址,而把p称为指针实属习惯称呼。
②指针的四大法宝:
1. 指针的类型
2. 指针指向的类型
3. 指针的值
4. 指针所占的内存区
(顺便可以温习一下英语,马上六级啦~)
首先(first and foremost),指针的类型----从语法角度上看,只要把指针声明语句中的指针名字去掉,剩下的就是指针的类型了。
例如:int *p; //指针的类型为int*
int (*ptr)[2]; //指针的类型为int (*)[2]
然后(secondly),指针指向的类型----从语法角度来看,把指针声明语句中的指针名字和指针声明符*去掉,剩下的就是指针指向的类型啦。
例如: int *p; //指针指向的类型为int
int (*ptr)[2]; //指针的类型为int [2]
此外(in addition),指针的值----是指指针本身存储的数值,这个值将被编译器当做一个地址而不是一个一般的数值。
例如: int a = 10;
int *p = &a; //p存放的值是a的地址,即&a.
最后(last but not least),指针本身所占据的内存区——在 32 位平台里,指针本身占据了 4 个字节的长度。
怎么样,这样看来是不是感觉指针也没那么可怕呢!一旦深入了解一点关于它的知识,感觉它也能和你成为朋友呢O(∩_∩)O,一起接着学习吧~
③指针的大小解析:
为什么指针的大小在32位系统下,其大小永远是四个字节呢?
首先我们先做一个类比,给你 1 位十进制数,你能够编号 10 个数(0~9),如果给你 2 位十进制数,则能够编号 100 个(0~99)……,对于计算机来说,底层所处理的数据都是二进制,一样的方式,给你 1 位二进制,只能编号 2 个数(0,1),给你 2 位二进制,则能编号4 个数(00,01,10,11),可以试想,,如果给你 n 位二进制,是不是就能编号 2^n 的状态。那么,现在,系统是 32 位的,则我们能够编号的范围是 0~2^32,即为 4G 的大小,这样一来,系统为了保证能够访问到任何一个地址,则我们的指针变量所占空间大小最起码的包含所有的地址表示,反过来,要想表示 4G 空间的大小,至少的 4 个字节,因此,指针的大小在 32 位系统下一定是 4 个字节,大了浪费,小了不能保证寻址所有空间。
(当知道这个之后,困惑许久的问题终于明白了,以后看到指针,就没有那种陌生感啦,(*^__^*) 嘻嘻...)
④数组指针 VS 指针数组
int (*p)[3]; // 数组指针
int *p[3]; // 指针数组
数组指针(int (*p)[3])与指针数组(int *p[3])从定义的形式上看,它们之间的差距仅在于是否有小括号,这也告诉我们,其二者差距的本质在于*与[]的结合律的问题,如果没有小括号,变量 p 先与[]结合,形成数组的概念,若有小括号,则变量 p 就与*号先结合成指针的概念,因此,[]的优先级比*高,能够认清这一点是关键。
⑤函数指针 VS 指针函数
int(*pfun)(int,int); // 函数指针
int* fun(int,int); // 指针函数
函数指针(int(*pfun)(int,int))与指针函数(int* fun(int,int))它们本质的区别也仅仅在于有无小括号(),这也体现出其本质下的真理,()结合律高于*,有括号则先结合形成指针的概念,只不过指针所指类型为函数,若没有括号在变量先与小括号结合,形
成函数的概念,只是函数的返回值为指针类型。
(注意,在定义函数指针时,一定要思考所指函数的原型,必须是返回值类型、参数的个数及类型完全一样,这样的指针才能接收其相应的函数地址,否者无法接收。)
⑥复杂指针
右左法则——首先从最里面的圆括号看起,然后往右看,再往左看,每当遇到圆括号时,就应该调转阅读方向,一旦解析完圆括号里面的所有东西,就跳出圆括号,重复这个过程直到整个声明解析完毕。
应该指出的是,在解析复杂指针时,应该从未定义的标识符开始阅读,而不是从括号阅读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个,在解析的过程中,做到心中有右左法则,而嘴上不说的境界。所谓复杂指针,个人认为,无外乎就是指针跟数组、函数的结合,外加括号多,星号多,从而导致一个指针的类型变得复杂多样化而已,不过只要掌握了方法,只要是能被定义出来的指针,无论怎样复杂都可以被解析。
复杂指针 1:
int * (* (*func) (int *)) [10]
解析:首先 func 是一个指针,该指针指向一个函数,函数的特征是具有一个整形指针参数和一个指针的返回值,该指针指向的是数组,数组具有十个元素,其中每个元素都是整形指针。
复杂指针 2:
int (*func)(int *, int (*)(int *));
解析: 首先 func 是一个指针,该指针指向一个函数,函数的特征是具有两个参数和一个返回值,其参数一个是整形指针参数,另一个是函数指针的参数,函数返回值为整形值。
复杂指针 3:
int (*func[5])(int *);
解析:首先 func 是一个数组,数组具有五个元素,其中每个元素都是一个指针,该指针指向函数,函数的特征是具有一个整形指针的参数和一个整形的返回值。
复杂指针 4:
int (*(*func)[5])(int *);
解析:首先 func 是一个指针,该指针指向数组,数组具有五个元素,每个元素都是指针,指针指向函数,函数特征为一个整形指针参数和一个整形返回值。
复杂指针 5:
int (*(*func)(int *)) [5];
解析:首先 func 是一个指针,指针指向函数,函数特征为一个整形指针参数和一个指针的返回值,其返回值指针指向的是具有五个整形数据的数组。
(当时,看完这些后,感觉恍然大悟,指针其实也没这么可怕啦~)