admin管理员组

文章数量:1487745

C语言(函数)

一、函数

1、函数的概念

C语言中的函数,准确来说应该叫子程序,与数学中的函数不同,C语言中的函数就是一个完成某项特定任务的一小段代码。这段代码是有特殊的写法和调用方法的。

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

在C语言中函数一般分为两类:库函数和自定义函数。

2、库函数

关于库函数我在这篇文章中已经简单梳理过 —> C语言基础, 还请跳转到这篇文章中,这里就不再赘述。

库函数的使用方法

3、形参和实参

关于形参和实参我也在下面这篇文章中简单介绍过 —> 指针的简单应用

这里再补充几点:(1)形参和实参是可以相同的

(2)在我们自定义的函数还未调用时,形参还没有在内存中开辟空间,只有在函数调用时才分配内存空间,这个过程就是形参的实体化;

(3)形参与实参是有联系的,但它们各自是独立的内存空间

4、return 语句

(1)return 语句后面可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果;

(2)return 语句后面也可以什么都没有,直接写 return;这种写法适合函数返回类型是 void 的情况;

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

(4)return 语句执行后,函数就彻底返回,后面的代码不再执行;

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

5、数组作函数参数

(1)数组在传参的时候,实参写数组名就行,形参可以是数组的形式也可以是指针的形式;

(2)实参和形参的名字可以是一样的,也可以是不一样的;

(3)数组传参的时候,传递的是地址。这是不同于变量传参的一个特殊点。至于为什么说两种不一样,请看我的这篇文章 —> 指针的简单应用

二、自定义函数

1、函数的语法形式

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

ret_type fun_name(形式参数) { 函数体; }

ret_type 是函数返回类型,fun_name 是函数名,圆括号中放的是形式参数,花括号中的是函数体。

我们可以把函数想象成一个小型的加工厂,工厂输入原材料,经过工厂加工才能生产出产品,函数也是一样,函数一般会输入一些值(可以是0个也可以是多个),经过函数内的计算,得出结果。ret_type 用来表示函数计算结果的类型,有时候返回类型可以是 void ,表示什么都不返回。 函数的返回类型与它的功能有关。

2、函数的举例

我们来写一个简单的加法函数,完成两个整型变量的加法操作:

上面我们写的加法函数是有返回值的,类型为 int 型。而有些函数是不需要返回值的,比如:

3、需要注意的地方

函数在设计的时候,一定要尽量功能单一,做到高内聚低耦合。

三、嵌套调用和链式访问

1、嵌套调用

嵌套调用就是函数之间的相互调用,每个函数就像一个乐高零件,通过相互配合来完成大型的问题。

假设我们要计算某年某月有多少天,我们来写一个函数实现:

代码语言:javascript代码运行次数:0运行复制
#include <stdio.h>

int is_leap_year(int year)//判断是否是闰年
{
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

int days(int year, int month)
{
	int arr[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };//定义一个数组来存放每月的天数,多
	                                                      //加了个0是为了使下标与月数对应
	int ret = is_leap_year(year);
	if (1 == ret && month == 2)//如果是闰年并且是2月,则天数+1
	{
		return arr[month] + 1;
	}
	else
	{
		return arr[month];
	}
}

int main()
{
	int year = 0;
	int month = 0;

	scanf("%d %d", &year, &month);
	int day = days(year, month);
	printf("%d年%d月有%d天\n", year, month, day);
	return 0;
}

上面的代码中我们写了两个自定义函数 is_leap_year() 和 days() ,在后面的函数中调用前面的函数,实现函数的简单嵌套。

其实稍微大一些的代码都是函数之间的嵌套调用,但值得注意的是,函数是不能嵌套定义的。关于函数定义我们接着往下看。

2、链式访问

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

这里我们先补充一个点,我们最熟悉的 printf()函数其实是有返回值的,其返回值为打印字符的个数。知道了这个我们再来猜一下上面代码的执行结果是什么?

想必聪明的各位已经计算出了结果。首先最里面的 printf()打印了43两个字符,所以返回2;次外面的 printf()打印2一个字符,所以返回1,再最外面的 printf()打印1,所以最终打印出了4321。

再看上面的代码,执行结果是 43 3 2,其说明了空格也是一个字符。

四、函数的声明和定义

1、单个文件

一般我们在使用函数的时候,直接将函数写出来(就是函数的定义)就使用了,就像我们之前写的代码。函数的定义就是一种特殊的声明。

但是,当我们把自定义函数放在主函数后,编译就会报错。为什么呢?

是因为编译器在编译时,会从上到下扫描代码,当扫描到主函数中的 print()函数时,由于编译器在这之前还未见过这个函数,所以就报了函数未定义。那如果我们就想将自定义函数放在主函数后呢?其实也是有办法的,这时候就用到了函数声明。

像上面这样把我们自定义函数的返回类型函数名这一行赋值粘贴到主函数之前,末尾加上分号就可以了。这就是函数的声明。函数或者变量都要先声明后使用。

在函数的声明中,形参的名字可以省略。 当然这点并不重要,一般我们为了方便直接复制粘贴即可。

2、多个文件

在未来我们写庞大的工程项目时,并不是在一个文件中编写的,而是在多个文件下。一个庞大的工程可以分成若干个文件,交由一个团队的不同成员编写,这就是模块化编程。模块化编程可以降低代码的复杂度、提高代码的复用性、可维护性、开发效率等。

那要怎么实现呢?

我们在源文件下新建一个 Add.c 文件 ,头文件下新建一个 Add.h 文件,我们将函数的定义(即函数的实现)放在 Add.c 文件下,将函数的声明放在 Add.h 文件下,再在 main.c 文件中包含头文件 “Add.h”(我们自己定义的头文件用双引号)就完成了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-05-09,如有侵权请联系 cloudcommunity@tencent 删除数组指针变量编译函数

本文标签: C语言(函数)