C语言函数详解

本文介绍了C语言中的函数概念,包括函数的定义、作用以及分类,如库函数和自定义函数。通过示例解释了如何使用函数,包括参数传递、函数调用和声明。此外,讨论了函数的嵌套调用和链式访问,强调了指针在函数参数传递中的重要性。
摘要由CSDN通过智能技术生成

目录

前言

函数的概念

什么是函数

为什么需要函数

函数的分类

库函数

自定义函数

函数的使用

函数的参数

函数的调用

函数的声明和定义

​编辑​ 函数的嵌套调用和链式访问

 函数的嵌套调用

链式访问

后语


一、前言

本篇文章是对C语言函数知识点内容上的介绍与讲解,相信各位看完之后肯定会对其有进一步的认识与理解。如果各位有发现任何错误或者需要更为细致的讲解欢迎各位评论或私信。

由于篇幅原因对于篇幅代码的分析内容还没有写出来,各位可以移步到下面链接的板书部分查看。

本篇文章所用到的代码与板书:Function


二、函数的概念

2.1什么是函数

  • 函数是一系列 C 语句的集合,能完成某个特定的功能。需要该功能的时候直接调用该函数即可,不用每次都堆叠代码。需要修改该功能时,也只需要修改和维护这一个函数即可。
  • 函数就是 C 语言的模块,一块一块的,有较强的独立性,可以相互调用。当一个函数模块需要另一个函数的功能的时候可以去调用,以实现其需要的功能。

2.2为什么需要函数

  • 方便代码重用。所谓“重用”,是指有一些代码的功能是相同的,操作是一样的,只不过针对的数据不一样,这时就可以将这种功能写成一个函数模块,以后用到这个功能时只需要调用这个函数模块就可以了,不需要再重复地编写同样的代码。这样可以解决大量同类型的问题,避免重复性操作。
  • 将语句集合成函数方便代码的维护。哪个功能出问题了,或者需要修改某个功能,那就只需要修改某个功能的函数就可以了。

三、函数的分类

函数分为:自定义函数和库函数

3.1库函数

  • 库函数是 C 语言平时常用的函数,为了方便程序员,给予给常用的函数。
  • 使用库函数,必须包含 #include 对应的头文件。

库函数我们可以通过
cplusplus.com学习。

我们利用strcpy这个函数来教你怎么使用这个网站 (跟详细使用教程已贴在板书部分)。

strcpy 

我们可以根据这个数组名,简单拆分成:string copy(字符串拷贝),其功能也是跟也是差不多的意思。

所以我们在设置自定义函数的时候也应该把函数名设置成与功能相匹配的名字,方便其代码的阅读。

下面我们写的代码让你更加深刻的了解strcpy函数这个函数的用法。

#include <string.h>//头文件 
//当我们使用库函数的时候都要引用头文件。
//我们常见的输出函数printf 就要引用头文件<stdio.h>
int main()
{
	char str1[] = "hunter";
	char str2[]="YYDS";
	strcpy(str1, str2);//我们把str2的YYDS复制到str1里面
	//复制的过程还把\0也复制进去了
	printf("str1: %s\nstr2: %s\n", str1, str2);
	return 0;
}

3.2自定义函数

自定义函数式程序员自己根据现实情况的需要设计设计的函数。我们需要自己设计函数名、函数的参数、函数的返回值、函数的实现。

ret_type   fun_name  (para1, ……)
{
      statement;//功能实现部分
}
ret_type 返回类型
fun_name 函数名
para1    函数参数

这里我们举个例子

  • 求两个数字相加
int Add(int a, int b)
{
	return a + b;
}

int main()
{
	int a = 10;
	int b = 20;
	int ret = Add(a, b);
	printf("%d", ret);
	return 0;
}
  • 交换两个数字 
void Swap1(int a, int b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

int main()
{
	int a = 10;
	int b = 20;
	Swap1(a, b);
	printf("a = %d\nb = %d", a,b);
	return 0;
}

​​​​​我们通过printf打印出来a和b的值,发现a和b这是没有变化。 

我这里我就我们就会得出一个疑问,为什么?他没有改变呢?

我们利用编辑器的调试功能进行调试,发现 a 和 b 传递的两个参数对应到 x 和 y ,发现这 a和 x,b 和 y 的地址根本都对不上,没有任何的关联性。所以当我们利用 Swap1 函数进行交换数值的时候只是说 x 和 y 在函数内部有交换的反应,而 x 和 y 跟 a 和 b 没有任何的关系。而当这个函数执行完毕之后,函数就会自动销毁。

所以我们就要想办法要让形参和实参用同一个地址,建立联系,这样我们就可以利用函数去实现两个数字的交换。

我前面有提到过一个东西叫做指针,指针可以用嗯来存放地址,然后利用这个地址可以去找到并且改变一个变量。

所以我们这边只需要实参传地址上去,并且拿一个指针去接收这个地址。然后我们就可以利用形参去改变实参。

那怎么利用这个去拿地址呢?

前面我也有提到过&(取地址符),现在我们开始写代码了。

void Swap2(int* x, int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	//Swap1(a, b); 
	Swap2(&a, &b);
	printf("a = %d\nb = %d", a,b);
	return 0;
}

 输出结果显示,我们能够正确的去交换两个数字。

四、函数的使用

4.1函数的参数

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

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

所以我们可以简单的认为:形参实例化之后其实相当于实参的一份临时拷贝。

当我们不需要用使用这个函数的返回值的时候,前面我们可以用void表示无返回值类型。

4.2函数的调用

传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

传址调用

传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。 这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

对于函数传值调用的使用我们要想清楚,不然会容易引起一些不必要的麻烦。

4.3函数的声明和定义

函数声明:

  • 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
  • 函数的声明一般出现在函数的使用之前。要满足先声明后使用。

函数定义:

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

函数调用:

  • 当我们需要使用函数的时候,只需要在使用的地方用函数名加上所传递的函数参数部分。

下面我们写一个Add函数,用来处理两个数字相加的结果。

int Add(int a, int b);//函数的声明

int Add(int a, int b)//函数的定义
{
	return a + b;
}

int main()
{
	int a = 10;
	int b = 20;
	int ret = Add(a, b);//Add(a, b)函数的调用
	printf("%d", ret); 
	return 0;
}

当我们把函数的声明删掉的时候,我们可以发现代码依然能够执行,编辑器并没有发生报错。

这个时候我们可以得出一个结论,函数的定义,是一种特殊的函数声明。所以当我们使用代写代码的时候,如果不要不想写函数的声明,就要把函数的定义放在所调用地方的上面。

因为函数执行的顺序在排除分支分支语句和循环语句的时候,就是按照顺序结构(从上往下)来执行的的。然后当遇到函数的调用就首先会从上面本代码以上的位置去寻找函数的定义和声明部分。如果发现也没有就会出现下面的错误。

​ 4.4函数的嵌套调用和链式访问

4.4.1函数的嵌套调用

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。

函数可以嵌套调用,但是不能嵌套定义。

下面这段代码的解析:

我们先创建了一个arr数组,数组里面有十个元素。分别给他初始化为1 2 3 4 5 6 7 8 9 10。然后利用 Fun 函数把前面五个元素初始化0。然后我们再在 Fun 函数里面嵌套调用一个print函数,想把这个初始化之后的数字打印出来。

void print(int arr[])
{
	for (int i = 0; i < 10; i++)
		printf("%d ", arr[i]);
}
void Fun(int arr[])
{
	print(arr);
	printf("\n");
	for (int i = 0; i < 5; i++)
	{
		arr[i] = 0;
	}
	print(arr);
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	Fun(arr);
	return 0;
}

4.4.2链式访问

把一个函数的返回值作为另外一个函数的参数。

根据我们上述提到的网站进行查询,我们可以得知。printf的返回值是打印参数的个数。 

int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    return 0;
}

 


五、后语

以上就是个人对于C语言的函数的了解与认识(关于函数递归部分我准备单独写一期)。希望能对各位对于学习 C 语言相关知识与认识有所帮助。如果各位有什么不懂的或者是需要有探讨的地方,欢迎留言和私信。码字不易,还请各位多多点赞。

欢乐的时间总是很短暂的,又到时间说拜拜,我们下一篇文章再见。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值