news 2026/4/28 21:48:42

C语言模块化灵魂——函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言模块化灵魂——函数

1、函数的概念

说起函数,我们在数学中已经有所了解,比如一次函数:y=kx+b,k和b都是常数,给一个任意的x就可以得到一个y值。

在C语言中,也有函数的概念,有人认为它是子程序。C语言中的函数就是一个完成某个任务的一小段代码。这段代码是有特殊的写法和调用方法的。

C语言的程序其实是由无数个小的函数而组成的,也可以这么说:一个大的计算任务可以分解成若干个较小的函数完成。同时一个函数如果能完成某项特定任务的话,这个函数也是可以复用的,这样就提升了开发软件的效率。

在C语言中我们一般会见到两类函数:

库函数和自定义函数

2、库函数

2.1标准库和头文件

C语言标准规定了C语言的各种语法规则,C语言并不提供库函数,C语言的国际标准ANSI C规定了一些常用的函数的标准,被称为标准库,那不同的编译器厂根据ASNI提供的C语言标准就给出了一系列函数的实现,这些函数就被称为库函数

我们前面提到的内容printf,scanf都是库函数,库函数也是函数,不过这些函数已经是现成的,我们只要学会就能直接使用了。有了库函数,一些常见的功能就不需要程序员自己实现了,一定提升了效率。

2.2库函数的使用方法

库函数的学习和查看有很多的工具,比如:

cplusplus.com - The C++ Resources Network

举个例子:sqrt

double sqrt(double x) //sqrt是函数名 //x是函数的参数,表示调用sqrt函数需要一个double类型的值 //double 是返回值的类型,表示计算的结果是double类型的值

2.21功能

sqrt函数能计算平方根

2.22头文件包含

库函数是在标准库中对应的头文件中声明的,所以库函数的使用,务必包含对应的头文件,不包含是会出现一些问题的。

2.23实践

#include<stdio.h> #include<math.h> int main() { double d = 16.0; double r = sqrt(d); printf("%lf\n", r); return 0; }

3、自定义函数

3.1函数的语法形式

其实自定义函数和库函数是一样的,形式如下:

ret_type name(形式参数) { }//ret_type是函数返回类型,name是函数名,括号里放的是形式参数(我们也叫形参),{}括起来的是函数体

我们可以把函数想像成一个小型工厂,工厂得输入原材料,经过工厂加工才能生产出产品,那函数也是一样的,函数一般会输入一些值(0到多个都有),经过函数的计算,得出结果。

其中ret_type是用来表示函数计算结果的类型,有时候返回类型可以是void,表示什么都不返回。

name是为了方便使用函数,就像人的名字一样,有了名字方便称呼,函数有了名字方便调用,我们一般根据函数的功能来命名。

函数的参数相当于,送入工厂的原材料,函数的参数可以是void,明确表示函数没有参数。如果有参数,要交代参数的类型和名字以及个数。

{}括起来的就是函数体,函数体就是完成计算的过程。

3.2函数的举例

写一个加法函数:

#include<stdio.h> int Add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); int r = Add(a, b); printf("%d", r); return 0; }

当然Add函数也可以进行简化:

int Add(int x,int y) { return x+y; }

这里需要注意的是:函数的参数部分(函数参数的个数,每个参数的类型,形参的名字)

4、形参和实参

在函数使用的过程中,把函数的参数分为,形参和实参。

再看看我们前面写的代码:

1 #include<stdio.h> 2 int Add(int x, int y) 3 { 4 int z = 0; 5 z = x + y; 6 return z; 7 } 8 int main() 9 { 10 int a = 0; 11 int b = 0; 12 scanf("%d %d", &a, &b); 13 int r = Add(a, b); 14 printf("%d", r); 15 16 return 0; 17 }

4.1实参

在上面的代码中,第2~7行是Add函数的定义,有了Add函数了之后,我们再看第13行对Add函数的调用。

我们把第13行调用Add函数时,传递给参数的a和b称为实际参数,也叫实参

实际参数就是真是传递给函数的参数。

4.2形参

在上面的代码中,第2行定义函数的时候,在括号里的x和y被称为形式参数,也叫形参

我们为什么叫它形式参数呢?如果只是定义Add函数而不调用的话,Add函数的参数x和y只能是形式上存在的,不会向内存申请空间,不会真实存在,所以叫形式参数。形式参数只有在函数被调用的过程中为了存放实参传递过来的值,才会向内存申请空间,这个过程就叫形参的实例化

4.3形参和实参的关系

虽然我们提到了实参是传递给形参的,他们之间是有关系的,但是形参和实参各自是独立的内存空间。实参的地址和形参的地址是不一样的,所以我们可以理解为形参是实参的一份临时拷贝

5、return语句

在函数的设计中,函数经常会出现return语句,这里讲一下return语句使用的注意事项。

return后面可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果。

return后面也可以什么都没有,直接写return;这种写法适合函数返回类型为void的情况。

return语句执行后,函数就会彻底返回,后面的代码将不再执行。

return返回的值和函数返回类型不一致,系统会自动将返回的值隐式转换为函数的返回类型。

如果函数中存在if等分支语句,要保证每一种情况都有return返回,否则会出现编译错误。

函数的返回类型如果不写,编译器会默认为int类型。

函数写了返回类型,但是函数中没有使用return返回值,那么函数的返回值是未知的。

6、数组做函数参数

在使用函数解决问题的时候,难免会将数组作为参数传递给函数,在函数内部对数组进行操作。

比如:写一个函数将一个整型数组的内容全部置为-1,再写一个打印数组的内容。

#include<stdio.h> int main() { int arr[]={1,2,3,4,5,6,7,8,9,10}; int num=sizeof(arr)/sizeof(arr[0]); set_arr(arr,num);//设置数组内容为-1 print_arr(arr,num);//打印数组 }

数组作为参数传递给set_arr和print_arr函数了,那这两个函数应该如何设计呢?

这里我们需要知道数组传参的几个知识点:

函数的形式参数要和函数的实参个数匹配

函数的实参是数组,形参也可以写成数组形式的

形参如果是一维数组,数组大小可以考虑不写

形参如果是二维数组,行可以省略,列不可以省略

数组传参,形参不会创建新的数组的

形参操作的数组和实参的数组是同一个数组

现在我们就可以实现这两个函数了:

#include<stdio.h> void set_arr(int arr[], int n) { int i = 0; for (i = 0; i < n; i++) { arr[i] = -1; } } void print_arr(int arr[], int n) { int i = 0; for (i = 0; i < n; i++) { printf("%d ", arr[i]); } } int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; int num = sizeof(arr) / sizeof(arr[0]); set_arr(arr, num); print_arr(arr, num); return 0; }

7、嵌套调用和链式访问

7.1嵌套调用

嵌套调用是指函数之间的相互调用,每一个函数就像是一块积木,正是因为多个积木相互无缝的配合才能搭建出精美的物件,也正是因为函数之间的相互调用才能写出相对大型的程序。

假如我们计算某年某月有多少天?如果要用函数实现,可以设计两个函数

leap_year():根据年份来确定是否是闰年

get_days_of_month():确实是否为闰年后,再根据月份计算天数

#include<stdio.h> int leap_year(int y) { if((y % 4 == 0)&&(y % 100 != 0)||(y%400==0)) { return 0; } else { return 1; } } int get_days_of_month(int y, int m) { int day[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; int d = day[m]; if (leap_year(y) == 0) { d += 1; } return d; } int main() { int year = 0; int month = 0; int days = 0; scanf("%d %d", &year,&month); days = get_days_of_month(year,month); printf("%d", days); return 0; }

在这个程序中,在get_days_of_month函数中调用了leap_year函数,当然在main函数中也有printf和scanf函数的调用等等。

7.2链式访问

所谓链式访问就是将一个函数的返回值作为另一个函数的参数,这样两个函数就像链条一样串在了一起,这就是函数的链式访问。

比如这样:

#include<stdio.h> int main() { int length=strlen("abcdef"); printf("%d\n",length); return 0; } #include<stdio.h> int main() { printf("%d\n",strlen("abcdef")); return 0; }

8、函数的声明和定义

8.1单个文件

一般我们使用函数时,直接将函数写出来使用。

比如像上面我们写的函数:

其中第475~484行是函数的定义,第489行是函数的调用

这种场景下函数的定义在函数的调用之前,没有问题。

如果我们将函数的定义放在函数的调用后面会怎样呢:

这个代码在VS2022上编译就会出现上面的警告。

因为编译器在进行编译时,是从第一行往下扫描的,当遇到leap_year函数的调用时,并没有发现前面的定义,就会发出警告。

要解决这个问题我们只需要在调用函数之前先声明一下leap_year函数,这个声明只需要交代清楚函数的返回类型,参数以及函数名就可以了,通俗一点就是先给编译器提个醒,告诉它我等下会用到这个函数的。

这样先定义函数,代码就可以正常编译了。

函数的定义也算是一种特殊的声明,所以先定义再调用也是可以的。

8.2多个文件

一般在企业我们写代码时,代码可能会比较多,不会将所有的代码都放在一个文件里,我们往往会根据其功能放在多个文件中。

一般情况下,函数的声明都放在头文件中(.h),函数的调用放在源文件中(.c)。

9、结语

再次更新,共同进步!

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

如何入门AI大模型应用工程师?你应该有这样的知识结构。。。

首先&#xff0c;你需要对这个岗位感兴趣&#xff0c;其次你需要有时间学习。好了&#xff0c;废话不多说&#xff0c;我们直接从求职要求开始。 01 RAG开发 什么是RAG? RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;一种将“信息检索”…

作者头像 李华
网站建设 2026/4/16 16:01:18

如何快速安装kill-doc:免费文档下载的终极指南

如何快速安装kill-doc&#xff1a;免费文档下载的终极指南 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档&#xff0c;但是相关网站浏览体验不好各种广告&#xff0c;各种登录验证&#xff0c;需要很多步骤才能下载文档&#xff0c;该脚本就是为了解决您的…

作者头像 李华
网站建设 2026/4/18 11:08:07

豆包 kubernetes-1.35.3/test/compatibility_lifecycle/cmd/feature_gates.go 源码分析

Kubernetes feature_gates.go 源码深度分析 文件路径:kubernetes-1.35.3/test/compatibility_lifecycle/cmd/feature_gates.go 核心定位:这是 Kubernetes 兼容性生命周期测试的命令行工具入口,专门用于解析、校验、导出 Kubernetes 特性门控(Feature Gates) 元数据,保障…

作者头像 李华
网站建设 2026/4/16 15:58:27

免费浏览器扩展:Markdown Viewer的完整使用指南与核心功能解析

免费浏览器扩展&#xff1a;Markdown Viewer的完整使用指南与核心功能解析 【免费下载链接】markdown-viewer Markdown Viewer / Browser Extension 项目地址: https://gitcode.com/gh_mirrors/ma/markdown-viewer 你是否经常需要在浏览器中查看Markdown文档&#xff0c…

作者头像 李华