news 2026/9/27 22:03:59

初识函数调用、嵌套调用、链式访问、函数递归

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
初识函数调用、嵌套调用、链式访问、函数递归
  1. C语言学习记录

日期: 8.15

📖今日知识点 ——

1.函数是什么

  1. 维基百科中对函数的定义是 —— 子程序
  2. 在计算机科学中,子程序是一个大型程序中的某部分代码,有一个或多个语句块组成。它负责完成某项特定任务,而且相较于其它代码具备相对独立性。
  3. 一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成软件库。
  4. 函数的分类:库函数、自定义函数

memory —— 记忆 —— 内存

memset —— 内存设置

2.库函数(使用库函数,必须包含#include对应的头文件)

  1. 在我们学习C语言编写的时候,总在一个代码编写完成之后迫不及待地想知道结果,想把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能:将信息按照一定的格式打印到屏幕上(printf)。
  2. 在编程的过程中我们会频繁的做一些字符串的拷贝工作(strcpy)。
  3. 在编程中会计算n的k次方这样的运算(pow)
  4. 常用库函数:
  • IO函数 printf scanf getchar
  • 字符串操作函数 strcmp strlen
  • 字符操作函数 toupper
  • 内存操作函数 memcpy memcmp memset

  • 时间/日期函数 time
  • 数字函数 sqrt pow
  • 其他库函数

3.自定义函数

自定义函数和库函数一样,有函数名,返回值类型和函数参数。但是不一样的是这些都是我们自己来设计。这给程序员一个很大的发挥空间。

函数的组成:

ret_type fun_name(para1, * )

{

statement;//语句项

}

ret_type 返回类型

fun_name 函数名

para1 函数参数

4.函数参数

实际参数(实参):真实传给函数的参数,叫实参。实参可以是:常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,他们都必须有确定的值,以便把这些值传送给形参。

形式参数(形参):形式参数指函数名括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内存单元),所以叫形式参数。形式参数当函数调用完成后就自动销毁了。因此形式参数只在函数中有效。

5.函数调用

  1. 传值调用:函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参
  2. 传址调用
  • 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数方式
  • 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

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

      函数不可以嵌套定义

      但是可以嵌套调用

      //函数可以嵌套调用

      void text3()

      {

      printf(“hehhe\n”);

      }

      int text2

      {

      text3(); return 0;

      }

      int main()

      {

      text2(); return 0;

      }

      链式访问

      7.函数的声明和定义

      函数声明:

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

      函数定义:

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

      如果定义在使用前就不用声明了

      8.函数递归

      什么是递归?

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

      递归的两个必要条件:

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

      写递归代码的时候:

      1. 不能死递归,要有跳出条件,每次递归逼近跳出条件
      2. 递归层次不能太深

      练习代码

      📖今日知识点 ——函数递归2

      上面有count变量,现在要求不允许创建变量,采用递归思想:大事化小

      my_strlen(“bit”);

      1+my_strlen(“it”);

      1+1+my_strlen(“t”);

      1+1+1my_strlen(“”);

      1+1+1+0=3

      💻练习代码

      #include <stdio.h>

      //求n的阶层(不考虑溢出)

      //n!=123…*n

      int main()

      {

      int n =0; scanf("%d",&n); int i = 0; int ret = 1; //循环是一种_**迭代**_ for (i = 1; i <= n; i++) { ret = ret * i; } printf("%d\n",ret); return 0;

      }

      递归的方式:

      //_递归_的方式解决求n的阶层(不考虑溢出)

      int Fac(int n)

      {

      if (n <= 1) return 1; else return n * Fac(n-1);

      }

      int main()

      {

      int n = 0; scanf("%d",&n); int ret = Fac(n); printf("%d\n",ret); return 0;

      }

      效率太低了,因为重复大量的计算。

      int count = 0;

      //递归可以求解,但是可能效率太低

      int Fib(int n)

      {

      //统计第3个斐波那契数的计算次数 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;

      }

      高效率(不考虑溢出)

      #include<stdio.h>

      //编写程序数一下 1 到 100 的所有整数中出现多少个数字9

      //9 19 29 …99

      //90 91 92…99

      int main()

      {

      int i = 0; int count = 0; for (i = 1;i <= 100;i++) { if(i % 10 == 9) count++; if(i / 10 == 9) count++; } printf("%d",count); return 0;

      }

      //计算1/1-1/2+1/3-1/4+1/5…+1/99-1/100的值,打印出结果

      int main()

      {

      int i = 0; double sum = 0; for (i = 1; i <= 100; i++) { if (i % 2 == 0) sum -= 1.0 / i; else sum += 1.0 / i; } printf("%1f",sum); return 0;

      }

      更简单的做法

      //计算1/1-1/2+1/3-1/4+1/5…+1/99-1/100的值,打印出结果

      int main()

      {

      int i = 0; double sum = 0; int flag = 1; // 符号标记:1表示当前项取正号,-1表示当前项取负号 for (i = 1; i <= 100; i++) { // flag * 1.0 / i: // 如果flag=1,就是 +(1.0/i) // 如果flag=-1,就是 -(1.0/i) // 这样就能实现 + - + - 交替 sum += flag * 1.0 / i; // 每加完一项,把符号取反: // 1 变成 -1,下一次就是减 // -1 变成 1,下一次又是加 flag = -flag; } printf("%f", sum); return 0;

      }

      //求十个整数中最大的值

      int main()

      {

      int arr[10] = {-1,-2,-3,-4,-5,-6,-7,-8,-9,-10}; int max = arr[0];//这里不应该为int max = 0;,因为要是数组里的为负数就比不了了 int i = 0; for (i = 0; i < 10; i++) { if (arr[i] > max) { max = arr[i]; } } printf("%d\n",max); return 0;

      }

      注释版

      //在屏幕中输出9*9乘法口诀表

      //1*1=1

      //21=2 22=4

      //31=3 32=6 3*3=9

      //…

      int main()

      {

      ** int i = 1; // i:行号**

      ** for (i = 1; i <= 9; i++) // 外层循环:打印 9 行**

      ** {**

      ** int j = 0; // j:每行第几列**

      ** for (j = 1; j <= i; j++) // 内层循环:第 i 行打印 i 列**

      ** {**

      ** printf("%d*%d=%-2d ", i, j, i * j);**

      ** // 三个 %d 依次对应:左因数 i、右因数 j、乘积 i*j**

      ** // %-2d:左对齐,至少占 2 格**

      ** }**

      ** printf(“\n”); // 一行打完,换行**

      ** }**

      ** return 0;**

      }

      ****

      第 1 题(单选题)

      题目:能把函数处理结果的二个数据返回给主调函数,在下面的方法中不正确的是:(A)

      A. return 这二个数 C 语言 return 只能返回 1 个值,不能直接 return 两个数

      B. 形参用数组

      C. 形参用二个指针

      D. 用二个全局变量

      第 2 题(单选题)

      题目:关于函数调用说法不正确的是:() A. 函数可以传值调用,传值调用的时候形参是实参的一份临时拷贝 B. 函数可以传址调用,传址调用的时候,可以通过形参操作实参 C. 函数可以嵌套定义,但是不能嵌套调用 D. 函数可以嵌套调用,但是不能嵌套定义

      C 语言函数不能嵌套定义,可以嵌套调用

      第 3 题(单选题)

      题目:在函数调用时,以下说法正确的是:()

      A. 函数调用后必须带回返回值

      B. 实际参数和形式参数可以同名

      C. 函数间的数据传递不可以使用全局变量

      D. 主调函数和被调函数总是在同一个文件里

      第 4 题(单选题)

      题目:关于函数的声明和定义说法正确的是:()

      A. 函数的定义必须放在函数的使用之前

      B. 函数必须保证先声明后使用

      C. 函数定义在使用之后,也可以不声明

      D. 函数的声明就是说明函数是怎么实现的

      第 5 题(单选题)

      题目:关于实参和形参描述错误的是:()

      A. 形参是实参的一份临时拷贝

      B. 形参是在函数调用的时候才实例化,才开辟内存空间

      C. 改变形参就是改变实参

      D. 函数调用如果采用传值调用,改变形参不影响实参

      第 6 题(单选题)

      题目:函数调用 exec ((v1, v2), (v3, v4), v5, v6); 中,实参的个数是:()

      A.3

      B.4

      C.5

      D.6

      

      答案 & 简要解析

      第 3 题:B

      解析:A void 函数无返回值;C 全局变量可以用来传数据;D 函数可以分在不同.c 文件。实参形参可以同名,作用域互不干扰。

      第 4 题:B

      解析:C 语言规则:先声明,后调用。定义就是实现代码,声明只告诉编译器函数原型。

      第 5 题:C

      解析:传值调用时,形参只是实参拷贝,修改形参不会影响实参,C 说法错误。

      第 6 题:B

      解析:逗号运算符,(v1,v2)整体是1 个实参;(v3,v4)是第 2 个;v5 第 3;v6 第 4 → 一共 4 个实参。

      递归

      版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
      网站建设 2026/9/27 22:03:54

      美食网站开发的意义选哪家好

      从零搭建美食网站:破解需求拖延与安全漏洞的实操指南 改个需求建站公司拖一周,这种体验谁懂?很多做美食垂直领域的运营者,最头疼的不是流量,而是后端响应慢、功能改不动,甚至刚上线就遭遇数据泄露。很多人以为【美食网站开发的意义】仅在于展示菜谱,其实核心价值在于构建一个高并发、高安全、可快速迭代的数字资产。…

      作者头像 李华
      网站建设 2026/9/27 22:03:52

      3步搞定怎么用wordpress打开网站图解步骤新手避坑指南

      3步搞定怎么用wordpress打开网站图解步骤新手避坑指南 很多新手卡在第一步就头晕,域名服务器搞不懂,对着浏览器地址栏发呆。别慌,这套怎么用wordpress打开网站图解步骤专治各种“小白症”。哪怕你连什么是DNS都没听过,跟着这篇实操指南,半小时就能让网站上线,并且做好基础SEO布局,让百度和…

      作者头像 李华
      网站建设 2026/9/27 22:03:43

      仁怀网站建设怎么选?避开备案坑的实战指南

      仁怀网站建设怎么选?避开备案坑的实战指南 备案流程一头雾水,导致网站上线周期从两周拖到两个月,这种痛点在仁怀本地企业中极其常见。很多老板想搞个官网展示酱酒品牌,结果卡在ICP备案环节,不知道材料怎么填,更不知道 怎么选 靠谱的技术方案来规避合规风险。…

      作者头像 李华
      网站建设 2026/9/27 22:03:29

      企业网站首页应如何布局适合什么场景

      5招搞定企业首页布局:不懂代码也能兼顾性能优化 很多老板盯着空白文档发呆,手里攥着预算却不敢动。不是不想做网站,是怕做出来的东西慢如蜗牛,或者被黑客挂了马。其实, 自己不会代码想做网站 ,真不是死胡同。现在的技术栈早就把复杂逻辑封装好了,你要做的只是选对“骨架”,再填进“血肉”。…

      作者头像 李华
      网站建设 2026/9/27 22:03:24

      不懂代码选外贸营销网站制作公司?这份避坑速查手册帮你省钱

      不懂代码选外贸营销网站制作公司?这份避坑速查手册帮你省钱 自己不会代码想做网站,是不是感觉头大?看着同行官网炫酷又专业,自己连域名和服务器都分不清,更别提怎么让Google收录了。别慌,这份【速查手册】就是为你准备的。在四川做外贸的老板们,经常问我:“找一家靠谱的外贸营销网站制作公司,到底要准备多少…

      作者头像 李华
      网站建设 2026/9/27 22:02:43

      让建站公司做网站需要什么?3步教你避开域名服务器坑

      让建站公司做网站需要什么?3步教你避开域名服务器坑 域名服务器搞不懂,是90%老板找建站公司时的第一道坎。很多人以为只要给个名字就能开工,结果在服务器配置和域名解析上卡了半个月。其实,让建站公司做网站,核心在于 怎么选 对的技术栈和明确的需求边界。…

      作者头像 李华