C语言进阶第三篇【指针进阶】(上)

简介: C语言进阶第三篇【指针进阶】(上)

前言:Hello!我是@每天都要敲代码。上一期我们一起学习了:字符指针的使用、指针数组和数组指针的理解、数组和指针的传参以及补充的一些练习题目<<传送门>>;还没有掌握的一定要去学习在看下面的知识点,因为指针的知识点都是连贯的!这一期我们将继续学指针剩余的内容,一起加油吧!


1. 函数指针

1.1 函数指针的理解和写法

我们先根据前面所学梳理清楚函数指针是什么?


int* p          整型指针---指向整型的指针---存放的是整型变量的地址

char* pc     字符型指针---指向字符型的指针---存放的是字符变量的地址

int(*p)[10]  数组指针---指向数组的指针---存放的是数组的地址

----------       函数指针---肯定就是指向函数的指针---存放的是函数的地址


我们推导出了函数指针的意义,那么怎么书写呢?


26cff1e4d3784d4ab2923e5e2afaf635.png


这里我只说两点:


1、我们发现数组指针和函数指针的书写形式很类似:int (*parr)[10] = &arr


                                                                                    int (*pf)(int,int) = &ADD


2、我们打印&ADD和ADD的地址居然也是一样的,也类似于数组&arr和arr;我们来做一下比较:


(1)数组名 != &数组名;两者不等价,前者取出来的是首元素的地址;后者取出来的是整个数组的地址

(2)函数名 == &函数名;两者是等价的,因为对于函数没有什么首元素的地址这一说


注意:()的优先级也要高于*号的,所以必须加上()来保证pf先和*结合


练习:有了上面的理解,我们不妨就拿一个例题来来练练手,看你是否真正理解掌握了函数指针的写法,例如:void test(char* str),函数指针怎么书写呢?void (*pt)(char*) = &test


1.2 函数指针的调用

我们还是先从已学的知识入手,然后剖析函数指针的调用


baeeea3753d345da968ed7910ba635a0.png


这里解释一下两点:


1、int (*pf)(int, int) = &ADD   等价于     int (*pf)(int, int) = ADD


2、int sum = (*pf)(2, 3)           等价于    int sum = pf (2, 3);这里的解应用*没有实际意思,是摆设


1.3 两段有趣的代码

1.3.1 代码1 (*(void (*)())0)()

( *( void (*)() )0 )() 我们先根据自己的想法通俗理解一下:将0强制类型转换为函数指针,然后解应用,在调用。


解析:


1、从数字0开始着手,想让数字0作为地址,肯定要是一种指针类型才可以;

2、把0强制类型转换为函数指针类型,0作为函数的地址;

3、0放到函数指针类型里是无参的,返回类型是void;

4、然后开始调用,我们解应用括号括起来,()代表我们调用它,参数什么都不传;

总结:


调用0地址处的函数;该函数无参,返回类型是void

1、void(*)()---函数指针类型

2、(void (*)())0---对0进行强制类型转换,被解释为一个函数地址

3、*(void (*)())0---对0地址进行解引用操作

4、(*(void (*)())0)()---调用0地址处的函数


1.3.2 代码2 void (*signal(int,void(*)(int)))(int)

void (* signal(int,void(*)(int)) )(int)我们还是要一步步拆分去理解


1、signal和()先结合,说明signal是函数名;

2、signal函数的第一个参数的类型是int第,二个参数的类型是函数指针;该函数指针,指向一个参数为int,返回类型为void的函数;

3、signal函数的返回类型也是一个函数指针;该函数指针,指向一个参数为int,返回类型为void的函数;所以,signal是一个函数的声明;

4、void (*)(int) signal(int,void(*)(int))我们也可以这样理解,signal函数的返回类型是一个函数指针;但是语法上不能这样写,只能把返回类型写中间;


简化:signal是一个参数函数指针,它的返回类型又是一个函数指针;那我们怎么优化呢?


利用typedef-对类型重定义:typedef void(*) (int) pfun_t;对void(*)(int)的函数指针类型进行重定义为pfun_t;但是这种语法是不支持的,我们要把pfun_t写到中间:


typedef void(*pfun_t) (int);重名之后上面代码就可以拆分成:


void (*)(int) signal(int,void(*)(int)) 和typedef void(*pfun_t) (int)等价于pun_t signal(int,punt)


是不是更加的容易理解了?


2. 函数指针数组

2.1 函数指针的理解和写法

我们先给出对于函数指针数组的理解:存放函数指针的数组;


我们在一起回顾一下整型指针数组:整型指针 int*,整型指针数组 int* arr[10];那么函数指针数组怎么定义和使用呢?我们通过一段代码的形式去理解。

4a5cf3cccdfd495ab6139d5dfd9316bf.png



2.2 函数指针的实际应用

那么函数指针在实际写代码中有什么应用呢?我们就通过一个典型的计算器来对比学习;比如:我们要实现加、减、乘、除。


2.2.1 普通方法实现计算器

b5c5293acb464309abd32ece9104bc65.png


我们从switch中就可以看出,代码很冗余。那我们思考一下:


1、如果把 printf("请输入两个操作数:>");scanf_s("%d %d", &x, &y);这两句代码全部提炼出去放到switch最前。printf("ret=%d\n", ret);这句代码提炼出区放到后面不久可以避免代码冗余了?


2、但是这样会出现我们问题,当我们选择5错误或者选择0退出时,它还是要让我们输入两个操作数才能退出,这就很怪异;包括打印也是,我们只有正确调用了函数,才能打印;所以这种方法并不可取;怎么办呢?下面我们就用函数指针数组来优化这个代码!


2.2.2 函数指针数组实现计算器


af239986fea44ab79cc23680e5e2cc8d.png

我们利用函数指针数组来实现计算器,即解决了代码冗余的问题,而且还让代码更加的简练了,是不是很妙?这里函数指针数组parr相当于一个跳板的作用,我们经常把这样的数组叫做转移表!


函数指针数组的用途:转移表


相关文章
|
4月前
|
C语言
【c语言】指针就该这么学(1)
本文详细介绍了C语言中的指针概念及其基本操作。首先通过生活中的例子解释了指针的概念,即内存地址。接着,文章逐步讲解了指针变量的定义、取地址操作符`&`、解引用操作符`*`、指针变量的大小以及不同类型的指针变量的意义。此外,还介绍了`const`修饰符在指针中的应用,指针的运算(包括指针加减整数、指针相减和指针的大小比较),以及野指针的概念和如何规避野指针。最后,通过具体的代码示例帮助读者更好地理解和掌握指针的使用方法。
90 0
|
2月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
124 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
2月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
182 9
|
2月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
64 7
|
3月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
268 13
|
3月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
90 11
|
3月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
3月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
221 3
|
3月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
3月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
72 1