C语言·深入理解指针(三)

1. 字符指针变量

        通过已知的知识,我们知道字符变量的地址可以这么存储

                            

        当然,还有另一种书写方式

2. 数组指针变量

        区别与指针数组(存放指针的数组),数组指针是指向数组的指针,就如同整形指针是指向整形的指针,字符指针是指向字符的指针,它们都是指针变量

        下标引用(变址)操作符结合性高于解引用操作符,所以在定义  指针数组  和  数组指针  的时候是有很大区别的

        我们尝试存储一下数组的地址

        值得注意的是,如果粗暴的用数组指针来操作一维数组是很麻烦的:

        所以数组指针多用于操作二维数组。

3. 二维数组传参的本质

        首先我们回忆一下一维数组传参的内容,在形参部分我们有两种写法:1.写成数组的形式接收    2.写成指针的形式接收

        在扫雷程序中我们在二维数组的传参过程中是用到了  写法1:二维数组的形式来接收二维数组,那么二维数组传参有没有办法写成指针的形式接收

4. 函数指针变量

4.1 函数指针变量的创建

        如同整形指针,字符指针,数组指针,函数指针变量是用来存放函数的地址的

        我们尝试打印观察一下函数的地址

            

        数组名----是指向数组首元素的地址         &数组名----是指向整个数组的地址

        与其不同的是, 函数名 和 &函数名 是完全等价的

        下面我们尝试创建并使用一个函数指针变量

        在定义函数变量的时候首先声明这是一个指针

                *pf

        然后声明这个函数形参的类型,但由于结合顺序的愿意要给指针打上括号

                (*pf)(int, int)

        最后声明函数的返回值

                int (*pf)(int, int)

        如此便完成了一个函数指针的定义

4.2 两段有意思的代码

                        

        这段代码是一次函数调用

        1. 把0这个整形变量强制类型转换成一个函数指针,这个函数没有参数,没有返回值

        2. 然后调用0地址处的函数

        详解:

        首先可以看出来 void (*)() 是一个函数指针类型(不是函数指针变量)

        然后 (void (*)())0 将 (int)0 强制转换成这个函数指针类型,所以说现在0从一个整形变量成为了一个指针变量

        最后 (*(void (*)())0)() 解引用 0 地址处的这个函数再传参void,相当于调用了这个函数

        ​​​​​​​        

        这段代码是一次函数声明

        首先函数名叫 signal

        函数有两个参数,类型分别是 int 和 void(*)(int)

        函数返回值是 void (*)(int) 这种类型函数指针

4.3 typedef关键字

        typedef是用来类型重名的,可以将复杂的类型简单化

        如果你觉得unsigned int写起来太复杂,你可以再主函数开始前写上        

                typedef unsigned int uint;

        这样之后就可以只写uint来定义无符号整形变量

        数组指针 和 函数指针 也可以这样操作,但过程有些不同,要将改后的类型名放在括号里

        既然已经了解了如何简化类型名,那我尝试简化一下刚才的声明

                        

5. 函数指针数组

        把函数的地址放在一个指针里,那这个数组就叫函数指针数组

        我在这段代码中写了加减乘除4中函数(add,sub,mul,div),又用了两种方式书写函数指针数组,第一种是粗暴的定义一个数组和数组指向的元素,第二种是用typedef关键字自己定义好函数类型的类型名,然后再定义数组及其指向元素,我认为第二种定义方式更加直观。

        然后我通过访问数组元素获取函数地址,再输入参数进行函数运算,并打印运算结果。

        在访问数组元素调用函数时我也用到了两种方法,第二种比较直观,我就不过多赘述了,直接解释第一种:

        *(pfarr + i)找到数组元素,也就是函数地址,此时其实已经可以直接输入参数进行函数操作了,但是要注意加括号 (*(pfarr + i))(参数,参数),因为如果不加括号的话参数的括号结合顺序是要比 * 高的,那算出来的就不是我们想要的函数了,当然你注意到我在 (*(pfarr + i)) 的基础上又加了一层解引用变成 (*(*(pfarr + i)))  ,根据前文讲解的知识可以知道这其实没什么用,就是这么写,会,额,emmm,昂,麻烦一点。

6. 转移表

        将函数地址储存在数组之中,通过数组元素调用函数的方法被叫做转移表

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值