关于函数概述

目录

一.什么是函数:

二.为什么需要函数:

三.函数的使用:

1).函数的形式参数与实际参数:

2).库函数的调用:

 3).自定义函数的定义:

4).自定义函数的调用:

5).函数的声明:

6).函数的嵌套调用:

7).函数的链式访问:

四.传值调用和传址调用:


一.什么是函数:

       函数就是 C 语言的一个功能模块,有较强的独立性,可以相互调用,换句话说,C 语言中,函数是C语言的功能单位,实现一个功能一个函数,并且在一个函数里面可以调用 n 个函数,即大函数调用小函数,小函数又调用“小小”函数……等。

二.为什么需要函数:

1.将功能封装成单个函数后,方便代码的维护和bug的修改以及功能的更改。

2.将功能整合成函数后有利于功能的多次利用,换句话说,当需要该功能的时候,可以直接调用函数,避免重复编写相同的代码,使整体更加简洁。

三.函数的使用:

1).函数的形式参数与实际参数:

实际参数:

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

形式参数:

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

#include<stdio.h>
int add(int x, int y)
{
	return x + y;
}
int main()
{
	int a = 10; 
	int b = 20;
	add(a, b);
	return 0;
}

这里函数中的 x,y 便是复制 a,b 而来的形式参数,函数调用时的 a,b 便是实际参数。 

注:函数的实参需要与函数形参个数相同且顺序相同,数据类型一一对应。

2).库函数的调用:

一些基础功能或操作总被频繁的使用。比如:把数据信息按照一定格式打印到屏幕上(printf);拷贝字符串strcpy;计算k的n次方(pow)等等,C语言把这些基础功能或操作集成库,并根据C语言的标准规定了库的标准,统称为库函数。

示例1:

#include<stdio.h>
int main()
{
	printf("2");
	return 0;
}

结构如下所示:

 这里#include<stdio.h> 是声明库函数所属的头文件,通过库函数内的函数 printf 将2打印在屏幕上。

示例2:

#include<stdio.h>
#include<math.h>
int main()
{
	double a = 4.0;
	printf("%lf", sqrt(a));
	return 0;
}

结果如下图所示:

这里声明了另一个库函数所在的头文件 math.h,并调用了函数 sqrt 求出了 a 的平方根。

注:在代码中使用库函数前,应去学习网站搞清楚它的头文件参数和参数类型返回值和返回值类型库函数名库函数功能 以及 语法规则

 3).自定义函数的定义:

示例:


int/*返回值类型*/  max/*函数名*/(int x, int y)/*函数参数*/
{
	return x > y ? x : y;//函数体
}

由上我们可以知道,自定义函数由函数返回值类型、函数名、函数参数、函数体 组成。

这里我们定义了一个函数返回值类型为 int 类型,名为 max 、参数为两个 int 类型的函数,返回两个参数中的最大值的函数。

示例2:

int fun(int x)
{
	return x * x;
}

这里我们定义了一个返回值类型为 int 类型,函数名为 fun 、参数为一个 int 类型,返回值为参数(形式参数)的平方 的函数。

注:函数定义时,可以无参数,当不需要返回值时,可以将返回值类型位置天上void。

        函数定义时函数名不可重复。

        在一个函数中定义的变量,只能在本函数中用 (局部变量)。

4).自定义函数的调用:

示例:

#include<stdio.h>
int/*返回值类型*/  max/*函数名*/(int x, int y)/*函数参数*/
{
	return x > y ? x : y;//函数体
}
int main()
{
	printf("%d", max(3, 6));
	return 0;
}

运行结果如下图所示:

这里我们通过调用函数 max 求出了 3和6 之中的最大的数。

示例2:

#include<stdio.h>

int fun(int x)
{
	return x * x;
}
int main()
{
	printf("%d", fun(3));
	return 0;
}

运行结果如下图所示: 

这里我们调用名为 fun 的函数,求出参数 3 的平方。

5).函数的声明:

如果使用用户自己定义的函数,而该函数与调用它的函数(即主调函数)不在同一文件中,或者函数定义的位置在主调函数之后,则必须在调用此函数之前对被调用的函数作声明。

示例:



#include<stdio.h>

int fun(int x);
int main()
{
	printf("%d", fun(3));
	return 0;
}
int fun(int x)
{
	return x * x;
}

运行结果如下图所示:

 

 由此我们可以知道,函数的声明就是将函数的返回值类型,函数名,参数 放在调用函数时的上面,换句话说就是告诉编译器有这么一个函数。

注:一个函数只能定义一次,但是可以多次声明。

6).函数的嵌套调用:

顾名思义,就是在一个函数中再次调用函数,这个函数可以是函数本身的也可以是其他函数。

当函数自己调用自己时,也被称为函数递归

示例1:

#include<stdio.h>
int fun(int x)
{
	if (x == 3)
		return 3;
	return fun(x - 1);
}
int main()
{
	printf("%d", fun(10));
	return 0;
}

运行结果如下图所示:

 

这里,我们可以看到 fun 函数嵌套到 fun 函数中,即在 fun 函数中,再次调用 fun 函数,当参数 x 为 3时,返回3。

示例2:

#include<stdio.h>
int fun(int x)
{
	return x - 1;
}
int max(int x, int y)
{
	int c = x > y ? x : y;
	return fun(c);
}
int main()
{
	printf("%d", max(10, 20));
	return 0;
}

运行结果如下图所示:

相同的,这里我们可以看到 max 函数中嵌套了 fun 函数,通过函数max 求出10和20 中最大的值,并在返回时嵌套调用函数 fun 将最大值减一。

注:函数嵌套的层级应该合理控制,避免嵌套层级过深。 过多的嵌套层级会导致代码的可读性下降,增加调试和维护的难度。

       函数的嵌套使用应当遵循顺序依赖。 即在调用一个函数之前,被调用的函数必须已经定义。           函数嵌套虽然提供了较高的灵活性,但也增加了代码的复杂性。 在使用函数嵌套时,需要权衡可读性和简洁性之间的关系,避免过度使用函数嵌套。

7).函数的链式访问:

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

示例:

#include<stdio.h>
int add(int x)
{
	return x + 1;
}
int max(int x, int y)
{
	return x > y ? x : y;
}
int main()
{
	printf("%d", max(10, add(19)));
	return 0;
}

运行结果如下图所示:

 

显而易见,这里函数 add 的返回值用作函数 max 的参数,函数 max 的返回值又用作函数 printf 的参数,从而得到打印20的结果。

四.传值调用和传址调用:

传值调用:在函数调用过程中,传值调用将实参的数据(而不是地址)传给了形参,
在被调用的函数中,形参值改变了,但是不影响主调函数的实参值
参数传递方向是由实参向形参单向传递

示例:

#include<stdio.h>
int fun(int a)
{
	a++;
	printf("%d\n", a);
	return a;
}
int main()
{
	int a = 5;
	fun(a);
	printf("%d", a);
	return 0;
}

运行结果如下图所示:

 

易知,传值调用时,对形参的改变不影响实参。

传址调用:传址调用传值调用不同,传址调用是将实参变量的地址传给形参,(此时形参是指针,即让形参的指针指向实参地址)改变形参的同时也把实参改变了。

#include<stdio.h>
int fun(int* a)
{
	(*a)++;
	printf("%d\n", *a);
	return *a;
}
int main()
{
	int a = 5;
	fun(&a);
	printf("%d", a);
	return 0;
}

运行结果如下图所示:

 

可以发现 a 的值发生了改变。

 函数参数调用归根揭底就是创建一个新的变量(形式参数),将实际参数的内容复制到新变量中,这里我们改变新变量的值和实际参数毫无关系,但是传址调用,通过地址可以找到存放数据的地方,这时候改变数据就是改变实际参数。

  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值