程序内的部件加工厂

本文详细解析了C语言中的函数概念,包括函数的定义、分类(库函数和自定义函数)、参数的使用(传值调用与传址调用)、嵌套调用、链式访问以及递归的基本原理和应用实例,帮助读者深入理解C语言中的函数机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1万多个零部件在汽车加工厂内就可以打造成一台普通小汽车,而两百多个手机零件在手机加工厂就可以做成一部手机。而我们所学习的C语言中,也存在一家一家的"零部件加工厂"

在这里插入图片描述

零部件加工厂"函数"

函数的定义

在计算机程序当中所谈论的函数并不是我们数学中所使用的函数,函数在计算机程序中通常是由一条或多条语句实现的功能,封装以后便称之为函数。例如说scanf、printf这类关键词称之为输入输出函数。
函数也被定义为子程序

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

C语言中函数的分类

1 库函数
2.自定义函数

库函数

在使用C语言编写代码时,我们要做的第一步就是要引用头文件,例如#include <stdio.h>stdio.h这就是所谓的标准库,而引用标准库(头文件)之后才可以使用的某些函数就是库函数,例如输出信息到屏幕上的printh,读取键盘上输入值的scanf这些函数都是封装在stdio这个库里面的,所以说,在使用函数时,我们首先要了解对应的库文件。

自定义函数

自定义函数与库函数恰恰相反。它与库函数的组成结构是相同的,有函数参数,返回值,函数名。最大的差异就是自定义函数是由每一个程序员自己设计封装的,通俗来讲,由程序员们自己设计的函数称之为自定义函数,并且,当我们设计的自定义函数达到一定数量时,我们可以封装在自己的库中,也就是自定义库

函数的组成

介绍了这么多,那么我们接下来通过介绍一个简单的自定义函数来向大家展示函数的结构是由什么?又如何组成的。

//当不使用函数时完成两个数值相加的实现方式
int main()
{
	int a = 1;
	int b = 2;
	int sum = a + b;
	printf("%d",sum);
	return 0;
}
//创建相加函数完成两个数值的相加
int Add(int x,int y)//Add为函数名,int x,int y为函数参数,Add前的int为返回值类型
{
	int ret = x + y;
	return ret;//返回值
}
int main()
{
	int i = 30;
	int j = 10;
	int ret = Add(i,j);//ret用来接收整形返回值,所以定义为整型变量
	printf("%d\n",ret);
	return 0;
}

自定义函数
在上面代码可以看到,当我们去完成一个需求,使用函数的方式会使我们整个工程十分的便捷。若使用常规方式,会让代码看起来十分的冗余。
那么如果要设计一个函数,要涉及的点分别为

  1. 返回类型
  2. 函数名
  3. 函数参数
    在设计一个函数时,我们要确定以上几点才可以设计出一个正常的函数,其中如果缺少或错误一个便会造成BUG。例如下例代码中我们接受返回值变量(ret)类型设置错误
    单精度浮点型变量无法对整形变量进行处理
    单精度浮点型变量无法对整形变量进行处理

函数的参数

在上文的相加函数代码中,我们也看到了如果要设计一个函数,那么函数的参数是必不可少的。那么函数的参数是如何使用呢?

参数是什么,该如何使用

当我们在使用函数的过程中,这个过程我们称之为函数调用,例如最开始学习的printf输出函数,当我们调用这个函数输出Hello World时,Hello World这段字符串便是我们给printf的形式参数

参数的类型

在C语言中,参数分为两类

  1. 形式参数(形参)
    形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内
    存单
    元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有
    效。
  2. 实际参数(实参)
    真实传给函数的参数,叫实参。
    实参可以是:常量、变量、表达式、函数等。
    无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形
    参。

我们使用两段代码来解释形参与实参的区别

形式参数传参
int Add(int x,int y)//这里Add创建了两个临时变量来接受a,b变量的值
{
	int ret = x + y;
	return ret;
}

int main()
{
	int a = 2;
	int b = 3;
	int sum = Add(a,b);//这里只是将a,b两个变量中的数值传给了Add
	printf("%d",sum);
	return 0;
}

在上述代码中,主函数中调用Add传递的a,b只是变量中的数值,而Add函数则是创建两个临时变量接受a,b两个变量的值,也就是说x,y只是作为a,b变量的一份临时拷贝,并非a,b变量本身,在这段代码运行过程中,a,b,x,y分别为四块空间。如下图,四个变量所开辟的空间地址各不相同,这种传参方式便为形参。
所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。
在这里插入图片描述
那么实参也就是传递给函数的参数与主函数中的参数为同一参数,同一块空间,更改代码后如下。

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

int main()
{
	int a = 2;
	int b = 3;
	int sum = Add(&a, &b);
	printf("%d", sum);
	return 0;
}

在这里插入图片描述
在这里传递给Add函数的&a,&b便是实际参数

函数的调用

在上述两段代码中,我们可以简单的认为实参与形参的区别便是易型参与实参的区别便是传参时使用的是Add(a,b)Add(&a,&b)的区别,那么这两种传参我们应该怎么区分他呢?

传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。使用方式也就是Add(a,b)直接传递变量的数值

传址调用

  1. 传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
  2. 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操
    作函数外部的变量。
    使用方式也就是取变量地址作为参数传递Add(&a,&b)

函数的多种使用方式

C语言标准规定中,函数的使用方式是具有多样性的,例如for循环,我们可以嵌套使用来达到 多层循环的效果,函数也同样可以这样使用

函数的嵌套调用

多个函数在使用的过程中,我们要创建不同的变量来达到函数传参的效果,每一次传参都要在主函数中进行,然而和循环语句相同的点就是,在每个函数空间中,我们可以直接调用另一个函数,这个过程就是嵌套调用

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void print(int x)
{
	printf("Hello,%d\n", x);
}
void Add(int x, int y)
{
	int sum = x + y;
	print(sum);
}
int main()
{
	int a = 5;
	int b = 5;
	Add(a, b);
	return 0;
}

在这里插入图片描述
在上述代码中,我们在Add函数中调用print函数直接将变量sum进行传值调用,这种在一个函数中调用另一个函数的方式就是嵌套调用。

函数的链式访问

函数的链式访问是指在一个表达式中依次调用多个函数,并且每个函数的返回值作为下一个函数的参数。这种方法可以使代码更加简洁和易读

示例代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Add(int x, int y)
{
	int sum = x + y;
	return sum;
}
int main()
{
	int a = 5;
	int b = 5;
	printf("%d", Add(a,b));
	return 0;
}

在这里插入图片描述
在上述代码,我们直接将函数表达式作为printf的参数,将Add的返回值作为传递给Printf的参数,这就是函数的链式访问一个简单的示意代码
接下来给大家看一段有代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Add(int x, int y);

int main()
{
	int a = 5;
	int b = 5;
	printf("%d", Add(a,b));
	return 0;
}
int Add(int x, int y)
{
	int sum = x + y;
	return sum;
}

如上代码,我们在调用Printf的传参过程中,并没有先创建一个变量作为接受Add返回的值进行传参,而是直接可以将Add函数作为参数传递。但是函数的链式访问并非没有限制,Add函数之可以这样使用,是因为Add函数声明时说明它会返回一个int整数,若函数并没有返回值,例如void Add(int x,int y),那么就不可以进行链式访问

函数递归

程序调用自身的编程技巧称为递归( recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的主要思考方式在于:把大事化小
举一个通俗的例子
从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?“从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?‘从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?……’”

函数递归的流程
在这里插入图片描述
我们可以使用一段简单的代码来更加清楚的递归
需求:求3的阶乘

//常规使用函数的方式来求3的阶乘
Int factorial(int x)
{
	int n = 1;
	int num = 0;
	while(n<x)
	{
		num = x * n;
		n++;
	}
	return num;
}
int main()
{
	int x = 3;
	printf("%d",factorial(x);)
	return 0;
}

//使用递归的方式求阶乘
int factorial(int x)
{
	if(x<=1)
	{
		return 1;
	}
	else
	return x * factorial(x-1);
}

int main()
{
	int n = 3;
	
}

可以看到,使用递归的情况下代码量整体减少,工作量大大减少,不需要过多的变量和过多的循环条件。
1. 许多问题是以递归的形式进行解释的,这只是因为它比非递归的形式更为清晰。
2. 但是这些问题的迭代实现往往比递归实现效率更高,虽然代码的可读性稍微差些。
3. 当一个问题相当复杂,难以用迭代实现时,此时递归实现的简洁性便可以补偿它所带来的运行时开销

如果此篇文章对您有所帮助,请点赞或留言鼓励一下吧,如果有哪里欠缺也可以评论指导~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值