博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C/C++学习笔记——C提高: 函数指针和递归函数
阅读量:4219 次
发布时间:2019-05-26

本文共 3167 字,大约阅读时间需要 10 分钟。

函数指针

函数类型

通过什么来区分两个不同的函数?

一个函数在编译时被分配一个入口地址,这个地址就称为函数的指针,函数名代表函数的入口地址。
函数三要素: 名称、参数、返回值。C语言中的函数有自己特定的类型。
c语言中通过typedef为函数类型重命名:

typedef int f(int, int);		// f 为函数类型typedef void p(int);		// p 为函数类型

这一点和数组一样,因此我们可以用一个指针变量来存放这个入口地址,然后通过该指针变量调用函数。

注意:通过函数类型定义的变量是不能够直接执行,因为没有函数体。只能通过类型定义一个函数指针指向某一个具体函数,才能调用。

typedef int(p)(int, int);void my_func(int a,int b){
printf("%d %d\n",a,b);}void test(){
p p1; //p1(10,20); //错误,不能直接调用,只描述了函数类型,但是并没有定义函数体,没有函数体无法调用 p* p2 = my_func; p2(10,20); //正确,指向有函数体的函数入口地址}

函数指针(指向函数的指针)

  • 函数指针定义方式(先定义函数类型,根据类型定义指针变量);
  • 先定义函数指针类型,根据类型定义指针变量;
  • 直接定义函数指针变量;
int my_func(int a,int b){
printf("ret:%d\n", a + b); return 0;}//1. 先定义函数类型,通过类型定义指针void test01(){
typedef int(FUNC_TYPE)(int, int); FUNC_TYPE* f = my_func; //如何调用? (*f)(10, 20); f(10, 20);}//2. 定义函数指针类型void test02(){
typedef int(*FUNC_POINTER)(int, int); FUNC_POINTER f = my_func; //如何调用? (*f)(10, 20); f(10, 20);}//3. 直接定义函数指针变量void test03(){
int(*f)(int, int) = my_func; //如何调用? (*f)(10, 20); f(10, 20);}

函数指针数组

函数指针数组,每个元素都是函数指针。

void func01(int a){
printf("func01:%d\n",a);}void func02(int a){
printf("func02:%d\n", a);}void func03(int a){
printf("func03:%d\n", a);}void test(){
#if 0 //定义函数指针 void(*func_array[])(int) = {
func01, func02, func03 };#else void(*func_array[3])(int); func_array[0] = func01; func_array[1] = func02; func_array[2] = func03;#endif for (int i = 0; i < 3; i ++){
func_array[i](10 + i); (*func_array[i])(10 + i); }}

函数指针做函数参数(回调函数)

函数参数除了是普通变量,还可以是函数指针变量。

//形参为普通变量void fun( int x ){
}//形参为函数指针变量void fun( int(*p)(int a) ){
}函数指针变量常见的用途之一是把指针作为参数传递到其他函数,指向函数的指针也可以作为参数,以实现函数地址的传递。//加法计算器int plus(int a,int b){
return a + b;}//减法计算器int minus(int a,int b){
return a - b;}//计算器#if 0int caculator(int a,int b,int(*func)(int,int)){
return func(a, b);}#elsetypedef int(*FUNC_POINTER)(int, int);int caculator(int a, int b, FUNC_POINTER func){
return func(a, b);}#endif

注意:函数指针和指针函数的区别:

  • 函数指针是指向函数的指针;
  • 指针函数是返回类型为指针的函数;

递归函数

递归函数基本概念

C通过运行时堆栈来支持递归函数的实现。递归函数就是直接或间接调用自身的函数。

普通函数调用

void funB(int b){
printf("b = %d\n", b);}void funA(int a){
funB(a - 1); printf("a = %d\n", a);}int main(void){
funA(2); printf("main\n"); return 0;}

函数的调用流程如下:

在这里插入图片描述

递归函数调用

void fun(int a){
if (a == 1){
printf("a = %d\n", a); return; //中断函数很重要 } fun(a - 1); printf("a = %d\n", a);}int main(void){
fun(2); printf("main\n"); return 0;}

函数的调用流程如下:

在这里插入图片描述

作业:

递归实现给出一个数8793,依次打印千位数字8、百位数字7、十位数字9、个位数字3。

void recursion(int val){
if (val == 0){
return; } int ret = val / 10; recursion(ret); printf("%d ",val % 10);}

递归实现字符串反转

int reverse1(char *str){
if (str == NULL) {
return -1; } if (*str == '\0') // 函数递归调用结束条件 {
return 0; } reverse1(str + 1); printf("%c", *str); return 0;}char buf[1024] = {
0 }; //全局变量int reverse2(char *str){
if (str == NULL) {
return -1; } if ( *str == '\0' ) // 函数递归调用结束条件 {
return 0; } reverse2(str + 1); strncat(buf, str, 1); return 0;}int reverse3(char *str, char *dst){
if (str == NULL || dst == NULL) {
return -1; } if (*str == '\0') // 函数递归调用结束条件 {
return 0; } reverse3(str + 1); strncat(dst, str, 1); return 0;}

转载地址:http://szxmi.baihongyu.com/

你可能感兴趣的文章
静态链表——sorting
查看>>
DFS——背包问题
查看>>
DFS——选数问题
查看>>
BFS——求矩阵中“块”的个数
查看>>
BFS——走迷宫的最小步数
查看>>
并查集——好朋友
查看>>
关键路径
查看>>
Web前端学习笔记——JavaScript之事件详解
查看>>
Web前端学习笔记——JavaScript之事件、创建元素、节点操作
查看>>
Web前端学习笔记——JavaScript之正则表达式、伪数组、垃圾回收
查看>>
Web前端学习笔记——JavaScript 之继承、函数进阶
查看>>
Web前端学习笔记——JavaScript之面向对象游戏案例:贪吃蛇
查看>>
不做单元测试?小心得不偿失!嵌入式系统单元测试工具,自动生成测试用例
查看>>
一种实用的联网汽车无线攻击方法及车载安全协议
查看>>
光靠欺骗检测是不够的:对抗多目标跟踪的攻击
查看>>
基于微区块链的V2X地理动态入侵检测
查看>>
面向V2C场景的ADAS数字孪生模型构建方法
查看>>
Comma2k19数据集使用
查看>>
面向自动驾驶车辆验证的抽象仿真场景生成
查看>>
一种应用于GPS反欺骗的基于MLE的RAIM改进方法
查看>>