【C语言】函数详解——库函数和自定义函数(超全)

【C语言】函数详解——库函数和自定义函数(超全)本文主要探讨 C 语言库函数和自定义函数的使用 函数的形参 实参 传值调用 传址调用 嵌套调用 链式访问 递归等 自定义函数

大家好,欢迎来到IT知识分享网。

前言

函数是什么?

函数是一个可以反复执行的程序段。在一个程序中,如果需要多次执行某项功能或操作,则可以把完成该功能或操作的程序段从程序中独立出来定义为函数,而原来程序中需要执行该功能或操作时可以通过函数调用来代替,以达到简化程序的目的。

函数的分类

一、库函数

1.什么是库函数?

库函数是将函数封装入库,供用户使用的一种方式。一些编写程序时会经常用到的功能,比如字符串的拷贝,求字符串的长度,计算n的k次方等,C语言的基础库中提供了一系列类似的库函数,方便人们使用,在使用时只需要添加它在所头文件即可。

2.库函数的学习和使用

#include<stdio.h> #include<string.h> int main() { 
    char str[] = ""; int n = strlen(str); printf("%d\n", n); return 0; } 

我们经常用到的printf和scanf也是库函数,其头文件是#include<stdio.h>

注:使用库函数,必须包含#include对应的头文件

这里分享几个学习库函数的工具

(1)MSDN应用

(2)www.cplusplus.com

(3)http://zh.cppreference.com

二、自定义函数

1.什么是自定义函数?

2.自定义函数的使用

1. 一个函数的返回类型如果写成void,表示这个函数不需要返回任何值。
2. 一个函数如果不写返回类型,默认返回int类型。

三、函数的参数

1.实际参数(实参)

2.形式参数(形参)

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

还是拿上面三个数相加的函数举例:

在这里插入图片描述

四、函数的调用

1.传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。
比如上面的求三数之和,我们只是把三个数相加的和返回,并没有改变三个实参。
但是如果我们想要交换两个数呢?传值调用可以实现吗?

试试下面的代码会出现什么情况

#include<stdio.h> void Swap(int x, int y) { 
    int tmp = x; x = y; y = tmp; } int main() { 
    int a = 0; int b = 0; scanf("%d%d", &a, &b); printf("交换前:x = %d, y = %d\n", a, b); Swap(a, b); printf("交换后:x = %d, y = %d\n", a, b); return 0; } 

2.传址调用

传址调用的经典例子就是交换两个数。上面的代码(传值调用)我们运行后,会发现a和b的值并没有发生变化,这是为什么呢?

在这里插入图片描述
在调用Swap函数时,形参x, y实例化分配了自己的空间,临时拷贝了实参a和b的值,当函数调用完成之后就自动销毁了,并没有对实参造成影响。

在这里插入图片描述

采用传址调用时,我们将a和b的地址传进去,形参用两个指针接收它们的地址,通过访问地址来修改这两个地址中的内容,也就是说函数内部可以直接操作函数外部的变量。
练习:写一个函数,每次调用时就会将num的值加一


#include<stdio.h> void test(int* p) { 
    (*p)++; } int main() { 
    int num = 0; test(&num); printf("%d ", num); } 

五、函数的嵌套调用和链式访问

1.嵌套调用

#include<stdio.h> void Print() { 
    printf("hello\n"); } void test() { 
    for (int i = 0; i < 5; i++) { 
    Print(); } } int main() { 
    test(); return 0; } 

2.链式访问

链式访问就是把一个函数的返回值作为另外一个函数的参数。

int len = strlen(""); printf("%d\n", len); 
printf("%d\n", strlen("")); 

二者本质一样,第二种就是链式访问

下面这道程序输出结果会是什么?

#include<stdio.h> int main() { 
    printf("%d", printf("%d", printf("%d", 43))); return 0; } 

六、函数的声明和定义

函数的声明一般出现在函数的使用之前,必须满足先声明后使用。

函数的声明一般要放在头文件中的,也可以不放。

#include<stdio.h> int Add(int x, int y) { 
     return x + y; } int main() { 
     printf("%d\n", Add(2, 3)); return 0; } 
#include<stdio.h> int Add(int x, int y);//函数的声明 int main() { 
     printf("%d\n", Add(2, 3)); return 0; } int Add(int x, int y)//函数的定义 { 
     return x + y; } 

在实际应用中,我们不会把所有的代码都放在一个源文件中。通常情况下,一个工程会分成不同模块,主程序、头文件、函数定义等,这样分工明确,不仅可以提高效率,还方便查找bug。

我们通常把函数的声明放在.h头文件中,函数定义放在.c源文件,主程序.c文件调用函数实现功能。

在这里插入图片描述
将头文件和源文件分开还可以实现代码的隐藏,让其他人可以使用你写的函数但看不到源码。
这个功能后续我会专门写一篇教程,就不在这里细说了。

七、函数递归

递归的定义

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

递归的两个必要条件

递归的优点和缺点

递归练习

递归递归,先递后归

解题思路:先将其数字一位一位的拆开,我们很容易想到取模的方法,先取出4,把4递推出去,然后是3,2,1。每次递归都会越来越接近边界条件,限制条件n >= 10,打印最后值1,然后函数回归依次打印2,3,4

#include <stdio.h> void Print(int n) { 
      if (n >= 10) { 
      Print(n / 10); } printf("%d ", n % 10); } int main() { 
      int num = 1234; Print(num); return 0; } 

再来一题

解题思路:n的阶乘 = n乘以(n-1)的阶乘 = n(n-1)乘(n-2)的阶乘…直到触发限制条件n==1,再回归。

#include <stdio.h> int fac(int n) { 
      if (n == 1) return 1; else return n * fac(n - 1); } int main() { 
      int num = 5; scanf("%d", &num); printf("%d\n", fac(num)); return 0; } 



免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/114237.html

(0)
上一篇 2025-12-09 22:00
下一篇 2025-12-09 22:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信