函数—C(下)

简介: 函数—C(下)

前言

在函数(1)中已经详细介绍了什么是库函数和自定义函数,以及函数参数的两种类型(实参和形参)的区别和用法。接下来将接着介绍函数的其他用法,让读者全面理解C语言函数用法以及背后得细节。

1. 函数的嵌套调用和链式访问

函数和函数之间可以根据实际需求进行组合,即相互调用。

1.1 嵌套调用

在C语言中,函数调用简单来说就是函数内部调用其他函数,以实现嵌套

 #include <stdio.h>

void new_line()
{
  printf("hehe\n");
}

void three_line()
{
  int i = 0;
  for (i = 0; i < 3; i++)
  {
    new_line(); //调用函数
  }
}

int main()
{
  three_line(); //调用three_line()函数
  return 0;
}

Tips:

函数可以嵌套调用,但不能嵌套定义。

1.2 链式访问

在C语言中,把一个函数的返回值作为另一个函数的参数叫链式访问。

#include <stdio.h>
int main()
{     //函数printf()的返回值作为了printf()的参数
  printf("%d\n", printf("%d\n", printf("%d\n", 43)));
  //注:printf()函数的返回值是打印在屏幕上字符的个数
  return 0;
}

2. 函数的声明和定义

2.1 函数声明

  1. 函数声明告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但具体是不存在的,函数声明决定不了。
  2. 函数的声明一般在函数使用之前,要满足先声明后使用。
  3. 函数的声明一般要放在头文件中。

2.2 函数定义

函数的定义是指函数的具体实现,交代函数的功能实现。

3. 函数递归

3.1 什么是递归

程序调用自身的编程技巧称为递归。

递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了程序的代码量。

递归的主要思想在于:把大事化小

//main()函数不断嵌套调用自身
//但由于没有相关限制,该程序会一直执行,死循环,最后栈溢出,程序结束
int main()
{
  printf("hehe\n");
  main();
  return 0;
}

3.2 递归的两个必要条件

前面一个程序我们已经见识到了如果递归没有相关条件限制,程序可能会出现异常。所以递归应满足以下两个必要条件:

  1. 存在限制条件,当满足这个限制条件时,递归便不再继续。
  2. 每次递归调用后越来越接近这个限制条件。

3.3 递归和迭代

3.3.1 练习1

求n的阶乘

函数实现功能参考代码:

int factorial(int n)
{
  if (n <= 1)
    return 1;
  else
    return n + factorial(n - 1);
  return 0;
}

3.3.2

求第n个斐波那契数(不考虑溢出)

函数实现功能参考代码:

int fib(int n)
{
  if (n <= 2)
    return 1;
  else
    return fib(n - 1) + fib(n - 2);
}

虽然上面两个函数可以实现需求,但我们会发现一些问题:

  • 使用fib这个函数的时候如果我们计算比较大的数(如第50个斐波那契数)时特别耗时间。
  • 使用factorial函数求第10000的阶乘时(不考虑结果正确性),程序会崩溃。

为什么呢?

  • 我们发现fib函数在调用过程中许多计算一直在重复。

以第40个斐波那契数,fib(3)被重复计算为例:

#include<stdio.h>
int count = 0;
int fib(int n)
{
  if (n == 3)
    count++;
  if (n <= 2)
    return 1;
  else
    return fib(n - 1) + fib(n - 2);
}
int main()
{
  int n = 0;
  scanf("%d", &n);
  int ret=fib(n);
  printf("%d\n", ret);
  printf("count=%d\n", count);
  return 0;
}

运行结果:

查看输出结果,我们发现第40个斐波那契数,fib(3)被重复计算39088169次,这是一个很大的数!

Tips:

  • 在调试函数时,日如果你的参数比较大,那就会报错:stack overflow(栈溢出),这样的信息。
  • 系统分配给程序的栈空间是有限的,但是如果出现死循环或者死递归时,这样可能导致一直开辟栈空间,最终产生栈空间耗尽的情况,我们称这种现象为栈溢出。

那要怎么解决问题呢?

  1. 将递归写成非递归
  2. 使用static对象替代nonstatic局部变量。在递归函数设计中,可以使用static对象代替nonstatic局部对象(即栈对象)。这不仅可以减少每次递归调用和返回时产生和释放的nonstatic对象的开销,而且static对象还可以保存递归调用的中间状态,并且可为各个调用层所访问。

比如下面代码采用了非递归的方式来实现:

//求n的阶乘
int factorial(int n)
{
  int result = 1;
  while (n > 1)
  {
    result *= n;
    n -= 1;
  }
  return result;
}
//求第n个斐波那契数
int fib(int n)
{
  int a = 1;
  int b = 1;
  int c = 1;
      
  while (n >= 3)
  {
    c = a + b;
    a = b;
    b = c;
    n--;
  }
  return c;
}

总结:

1.许多问题是以递归的方式来进行解释的,这只是应为它比非递归的形式更清晰。

2. 但这些问题的迭代实现往往比递归实现的效率要高,虽然代码的可读性稍差。

3. 当一个问题相当复杂时,难以用迭代实现时,此时递归实现的简洁性便可以补偿它运行时所带来的开销。

结尾

本片文章到此就圆满结束了。如果对你有帮助,记得点赞加关注哦!感谢您的支持!!

函数—C(上)


目录
打赏
0
0
0
0
10
分享
相关文章
环境变量配置 linux-Debian 实测-有效
环境变量配置 linux-Debian 实测-有效
152 0
GraalVM 24 正式发布阿里巴巴贡献重要特性 —— 支持 Java Agent 插桩
阿里巴巴是 GraalVM 全球顾问委员会的唯一中国代表,阿里云程序语言与编译器团队和可观测团队合作实现了 GraalVM 应用的无侵入可观测能力,并在 ARMS 平台上线了该功能。目前在 GraalVM 24 中发布的是支持 Java agent 的第一步,其余能力将在 GraalVM 的后续版本中陆续发布。
261 22
Centos6.5安装并配置Telnet服务
该内容是一个关于如何安装配置Telnet服务的教程。首先,通过yum安装vim、xinetd、telnet和telnet-server。接着,修改/etc/xinetd.d/telnet配置文件,将disable改为no,并设置访问限制(如限定特定网段和时间)。关闭防火墙,重启服务。创建测试用户后,分别使用CentOS和Windows的Telnet客户端进行连接测试,显示成功,实验完成。
542 1
云效产品使用报错问题之yaml发布不可以,限制直接执行如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
二叉树层序遍历及判断完全二叉树
二叉树层序遍历及判断完全二叉树
216 2
线上故障如何快速排查?来看这套技巧大全
有哪些常见的线上故障?如何快速定位问题?本文详细总结工作中的经验,从服务器、Java应用、数据库、Redis、网络和业务六个层面分享线上故障排查的思路和技巧。较长,同学们可收藏后再看。
线上故障如何快速排查?来看这套技巧大全
使用 OpenCV 和 Python 轻松实现人脸检测
本文介绍如何使用OpenCV和Python实现人脸检测。首先,确保安装了OpenCV库并加载预训练的Haar特征模型。接着,通过读取图像或视频帧,将其转换为灰度图并使用`detectMultiScale`方法进行人脸检测。检测到的人脸用矩形框标出并显示。优化方法包括调整参数、多尺度检测及使用更先进模型。人脸检测是计算机视觉的基础技术,具有广泛应用前景。
214 10
阿里云入选Gartner®分布式混合基础设施魔力象限
Gartner正式发布了《分布式混合基础设施魔力象限》(Magic Quadrant™ for Distributed Hybrid Infrastructure),阿里云在入选的中国厂商中于执行能力(纵轴)和愿景完整性(横轴)上均处在最高、最远的位置。
182 1
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问