C语言学习(8)-函数

目录

1. 函数的概念

2. 库函数

2.1 标准库和头文件

2.2 库函数使用举例

3. 自定义函数

3.1 函数的语法形式

3.2 函数举例

3.3 函数的声明与定义

4. 形参和实参 

4.1 实参

4.2 形参

4.3 形参和实参的关系

5. 数组做函数参数

6. return 语句


1. 函数的概念

数学中我们其实就见过函数的概念,比如:⼀次函数 y=kx+b ,k和b都是常数,给一个任意的x,就得到⼀个y值。

其实在C语言也引入函数(function)的概念,有些翻译为:子程序,子程序这种翻译更加准确⼀些。C语言中的函数就是⼀个完成某项特定的任务的⼀小段代码。这段代码是有特殊的写法和调用方法的。

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

  • 库函数
  • 自定义函数

2. 库函数

2.1 标准库和头文件

C语言标准中规定了C语言的各种语法规则,C语言并不提供库函数;C语言的国际标准ANSI C规定了⼀些常用的函数的标准,被称为标准库,那不同的编译器厂商根据 ANSI 提供的C语言标准就给出了⼀系列函数的实现。这些函数就被称为库函数。 我们前面内容中学到的 printf 、scanf 都是库函数,库函数也是函数,不过这些函数已经是现成的,我们只要学会就能直接使用了。有了库函数,⼀些常见的功能就不需要程序员自己实现了,⼀定程度提升了效率;同时库函数的质量和执行效率上都更有保证。 各种编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头文件中进行了声明。

库函数相关头文件https://zh.cppreference.com/w/c/header

有数学相关的,有字符串相关的,有日期相关的等,每⼀个头文件中都包含了,相关的函数和类型等信息,库函数的学习遇上再学习即可,不用特意去学习。

2.2 库函数使用举例

举例使用的是常用数学函数的库函数 math.h,使用其中的 sqrt 函数:

double sqrt(double x);
//sqrt 是函数名 

//作用:求平方根
//x 是函数的参数,表示调用 sqrt 函数需要传递⼀个 double 类型的值
//double 是返回值类型 - 表⽰函数计算的结果是 double 类型的值

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

#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 函数的语法形式

自定义函数

return_type function_name( parameter list )
{

        body of the function
}

在 C 语言中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:

  • 返回类型:一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
  • 函数名称:这是函数的实际名称,为了方便使用根据函数功能起有意义的名字。
  • 参数:参数就像工厂中送进去的原材料,函数的参数也可以是 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);

	//调⽤加法函数,完成a和b的相加
	//求和的结果放在r中
	int r = Add(a, b);

	//输出
	printf("%d\n", r);

	return 0;
}

函数的参数部分需要交代清楚:参数个数,每个参数的类型是啥,形参的名字叫啥。 上面只是⼀个例子,未来我们是根据实际需要来设计函数,函数名、参数、返回类型都是可以灵活变化的。

3.3 函数的声明与定义

一般我们在使用函数的时候,直接将函数写出来就使用了,比如上面那段代码,第3~8行是 Add 函数的定义,有了函数后,在第20行调用 Add 函数的。

但是如果我们将函数的定义放在函数的调用后面,如下:

#include <stdio.h>

int main()
{
	int a = 0;
	int b = 0;

	//输⼊
	scanf("%d %d", &a, &b);

	//调⽤加法函数,完成a和b的相加
	//求和的结果放在r中
	int r = Add(a, b);

	//输出
	printf("%d\n", r);

	return 0;
}

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

这个代码在VS上编译,就会出现警告。

这是因为C语言编译器对源代码进行编译的时候,从第一行往下扫描的,当遇到 Add 函数调用的时候,并没有发现前面有 Add 的定义,就报出了上述的警告。 要怎么解决这个问题呢?就是函数调⽤之前先声明⼀下 Add 这个函数,声明函数只要交代清楚:函数名,函数的返回类型和函数的参数。 如:int Add(int x, int y);这就是函数声明,函数声明中参数只保留类型,省略掉名字也是可以的。代码变成这样就能正常编译了。

#include <stdio.h>

int Add(int x, int y);

int main()
{
	int a = 0;
	int b = 0;

	//输⼊
	scanf("%d %d", &a, &b);

	//调⽤加法函数,完成a和b的相加
	//求和的结果放在r中
	int r = Add(a, b);

	//输出
	printf("%d\n", r);

	return 0;
}

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

4. 形参和实参 

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

4.1 实参

在上面的代码中,我们把第20行调用 Add 函数时,传递给函数的参数 a 和 b,称为实际参数,简称实参。 实际参数就是真实传递给函数的参数。

4.2 形参

在上面代码中,第定义函数的时候,在函数名 Add 后的括号中写的 x 和 y,称为形式参数,简称形参。

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

4.3 形参和实参的关系

虽然我们提到了实参是传递给形参的,他们之间是有联系的,但是形参和实参各自是独立的内存空 间。这个现象是可以通过调试来观察的。

我们在调试的可以观察到,x 和 y 确实得到了a和b的值,但是 x 和 y 的地址和 a 和 b 的地址是不一样的,所以我们可以理解为形参是实参的⼀份临时拷贝。 

5. 数组做函数参数

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

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

这里的 set_arr 函数要能够对数组内容进行设置,就得把数组作为参数传递给函数,同时函数内部在设置数组每个元素的时候,也得遍历数组,需要知道数组的元素个数。所以我们需要给 set_arr传递2个参数,⼀个是数组,另外⼀个是数组的元素个数。仔细分析 print_arr 也是⼀样的,只有拿到了数组和元素个数,才能遍历打印数组的每个元素。

#include <stdio.h>

void set_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		arr[i] = -1;
	}

}

void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	set_arr(arr, sz);//设置数组内容为-1
	print_arr(arr, sz);//打印数组内容
	return 0;
}

6. return 语句

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

  • return 后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执行表达式,再返回表达式的结果。 
  • return 后边也可以什么都没有,直接写 return; 这种写法适合函数返回类型是void的情况。
  • return 返回的值和函数返回类型不⼀致,系统会自动将返回的值隐式转换为函数的返回类型。
  • return 语句执行后,函数就彻底返回,后边的代码不再执行。
  • 如果函数中存在 if 等分支的语句,则要保证每种情况下都有 return 返回,否则会出现编译错误。
  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值