【摘要】指针作为C语言阶段最重要的部分,连接着C语言和数据结构,指针的出现,简化了代码,使得程序猿从大量的代码中解脱出来。但是随之而来的也是各种副作用。因此,你必须完全熟悉它,才可以利用好它来帮助自己。在之前的一篇博客中,我把指针的初级使用整理到一起,最近又学了些关于高级指针的知识,我也照例总结出来,希望会对你们有所帮助。
目录
1.指向指针的指针以及多级指针的运用
2.指针的高级声明(重点描述)
3.函数指针
4.字符串常量
一.指向指针的指针以及多级指针的运用
在讲这个知识点的时候,我觉得我应该把我之前遇到的一个问题给你们也看一看,当然我会把正确的结果也写出来
单看这个问题,你肯定可以很轻易的就得到这个答案,但是,如果稍微变一下呢
我只是把第五行改了一下,你觉得输出的结果会是什么呢?这次你可能就会犹豫一会了,但是我告诉你,答案和上面的一样。接下来我解释一下为什么是这样,这也是我当初想不通的地方
在第一个例子中,我定义了一个一级指针和一个二级指针,这两个指针一个存储变量 i 的地址,一个存储指针 pi 的地址,所以,一级指针解引用就是变量 i 的值,二级指针进行两次解引用也就是变量 i 的值,这个可以用一个图片来表示
通过这幅图,我们就可以很好地解释答案了
但是,第二个例子中,我没有定义二级指针,我只是定义了一个一级指针 ppi ,在 = 号的右边 ,是 & *pi,由于指针作为右值,就是一个地址常量,这个地址就是指向i的地址,所以再进行 & 之后,就是 i 的值,所以说,指针 pi 和指针 ppi 指向的都是 i 的地址,所以值是不变的。
指针可以进行多次定义,也可以进行多次间接访问,但是在一般的程序中,最多会碰到二级指针或者三级指针,如果遇到了更高阶的,我们也不用害怕,只要清楚它所指向的内容就可以准确的得到它的值
int i=10;
int *pi=& i;
int **ppi=& pi;
int ***pppi=& ppi;
别看定义了三阶指针,其实也不难,因为他们指向的都是前一个指针的地址,所以最后的结果都是10
二.指针的高级声明
要想搞清楚指针的高级声明,我想先给你看一些不同的声明,你看你能说对几个,我那时候刚看到真是错了好多
这里面就涵盖了指针高级声明的大多数。其中我认为比较难理解的就是倒数第二个,那我就把倒数第二个进行详细说明一下吧
int (*f[ ])( ) ,首先可以确定的是 f 一定是一个数组,*f[ ] ,那么数组里面的元素一定是整型指针类型的,然后第二个括号表明了 f 的身份是一个函数,所以整体理解起来就是 有一个 数组,里面存放的数据类型是函数指针 ,f 所指向的函数的返回值是int型
三.函数指针
对于函数,我们已经不陌生了,但是对于函数指针,我们了解的或许还很少,但是既然它也是一个指针,那他的一些用法还是和普通指针很类似的。、
1. 对函数指针进行间接访问时一定要进行初始化,让它指向某个函数。
int (*pf)(int )= &f;
这里就对 pf 进行了初始化,让它指向了函数 f
有一条要说的就是,函数名在被使用时编译器总会把它转换为指针函数,所以 & 符号可以加上也可以不加
2.通过使用函数指针,你可以实现回调函数,一个指向回调函数的指针作为参数传递给另一个函数
四.字符串常量
字符串常量有别于普通字符串的最大区别在于,普通的字符串是放在数组里面的,因此已经提前开辟好了空间将字符串挨个的放进去,但是字符串常量通常是放在只可读区,而通常有一个指针指向这个位置,所以字符串常量本身并没有存储空间,,它只是一个指针常量,也就无法进行修改。
既然是指针,那么我们也可以用下标引用,间接访问以及指针运算,所以,看看下面几种情况,你知道是什么意思吗?
1. "xyz"+1
因为定义的是一个字符串常量,因此本质上就是一个指针,对指针加 1 ,就是让它指向第二个字符,也就是指向 y
2. *"xyz"
因为字符常量类型是“指向字符的指针”,所以这个间接访问的结果就是它所指向的字符 x ,可不是整个字符串啊,不要把两个搅混了
3. "xyz"[2]
下标本质上和指针的 *没有区别,即让指针向后移两位,指向第三个字符 z
4. *("xyz" +4)
偏移量已经超过了字符串的范围,所以最终的值是一个不可预测的字符