C——函数

目录

1.函数的概念

2.库函数

2.1 标准库和头文件

2.2 库函数的使用方法

2.2.1 功能

2.2.2 头文件包含

3.自定义函数

3.1 函数的语法形式

3.2 函数的举例

4.函数的参数

4.1 实参

4.2 形参

5.return语句

6.数组做函数参数

7.嵌套调用和链式访问

7.1 嵌套调用

7.2 链式访问 

8. 函数的声明和定义

8.1 单个文件

8.2 多个文件


1.函数的概念

“函数”这个词我们大多是在数学中听到的,比如:一次函数 y = kx + b ,其中 k 和 b 都是常数,给自变量 x 一个值,就得到应变量 y 。

在C语言中也引入了函数(function)的概念,在一些地方翻译为子程序。C语言中的函数就是一个完成某项特定任务的一小段代码。这样的代码是有一定写法和调用方法的。

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

总结函数的好处:

1.可以拆分任务

2.可以复用,提升开发效率

在C语言中我们一般会见到两类函数:

1.库函数——是现成的,可以直接使用的函数

2.自定义函数——是根据需要,自己设计、创造的函数

2.库函数

2.1 标准库和头文件

C语言标准中规定了C语言的各种语法规则,C语言并不提供库函数;C语言的国际标准ANSI C规定了一些常用的函数的标准,比如 scanf ——它的名字、参数、返回类型、功能等等,被称为标准库。

不同的编译器厂商根据ANSI提供的C语言标准就给出一系列函数的实现,像微软的 MSVC ,苹果的 clang 等等,不同厂商函数的实现可能有差异,但是程序员使用时基本无感,这些函数就被称为库函数。

我们常用的 printf ,scanf 等等都是库函数,库函数属于是已经现成的函数,我们只需要学会就可以直接使用。库函数的使用使得一些简单的功能就不需要程序员自己实现了,一定程度上提升了效率;同时库函数的执行效率和质量都更有保障。

各种编译器的标准库中提供了一系列的库函数,这些库函数根据功能的划分,像字符相关的、内存相关的,等等,然后不同的这样一系列的、功能类似的库函数会放在同一个头文件里进行声明。

这里提供库函数的相关头文件:https://zh.cppreference.com/w/c/header

8af9d2ea1422471782094de8e901ff92.png

2.2 库函数的使用方法

库函数的学习和查看工具很多,比如:

C / C++ 官方的链接:https://zh.cppreference.com/w/c/header

cplusplus.com:https://legacy.cplusplus.com/reference/clibrary/

举例:sqrt

double sqrt (double x);
//sqrt 函数名
//x 是函数的参数,表示调用sqrt函数需要传递一个double类型的值
//double 是返回值类型 - 表示函数计算的结果是double类型的值

2.2.1 功能

Compute square root 计算平方根

Returns the square root of x.(返回平方根)

2.2.2 头文件包含

使用库函数必须包含#include 对应的头文件

使用举例:

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

3.自定义函数

如果库函数能干所有的事情,那还要程序员干什么?所以更加重要的是自定义函数。
自定义函数和库函数一样,有函数名,返回值类型和函数参数。但不一样的是这些都是我们自己来设计的。

3.1 函数的语法形式

ret_type fun_name(形式参数)
{

}

ret_type 返回类型

fun_name 函数名

{}内是函数体

3.2 函数的举例

1.写一个函数可以找出两个整数中的最大值。代码如下:

#include <stdio.h>

//设计的函数
int get_max(int x, int y)
{
	return (x > y) ? (x) : (y);
}


int main()
{
	int num1 = 10;
	int num2 = 20;
	int max = get_max(num1, num2);
	printf("max = %d\n", max);
	return 0;
}

函数的参数部分需要交代清楚:参数的个数,每个参数的类型是啥,形参的名字等等

我们可以根据实际需要来设计函数,它的函数名,参数,返回类型都是可以灵活变换的

小结:1.函数名是自定义的,根据实际情况起名字;

           2.参数的个数也可以根据实际情况来确定,可以有零个参数,也可以有多个参数;

           3.函数可以返回值,也可以不返回,函数不返回时,返回类型写 void。

4.函数的参数

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

这里放一个例子:

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int r = Add(a, b);
	printf("%d\n", r);
	return 0;
}

4.1 实参

在如上的代码中,2~5 行是Add函数的定义,有了函数以后,在12行调用Add函数。

我们将12行调用Add函数时,传递给函数的参数 a 和 b ,称为实际参数,简称实参。实参就是真实传递给函数的参数。

4.2 形参

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

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

fe17d1ce7cb4477f9e1a8e49d1bfe7b6.png

这里我们按F11进入调试界面监视变化,这里需要知道一点 :

X86 表示32位环境——编译生成的32位的程序

X64 表示64位环境——编译生成的64位的程序

F10 逐步监视,进入Add函数按F11,从上图可知:当实参传递给形参的时候,形参其实是实参的一份临时拷贝,对形参的修改是不会影响实参的。

5.return语句

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

· return 后边可以是一i个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果。

· return 后边也可以什么都没有,直接写 return ;这种写法适合函数返回类型时 void 的情况。

· return 返回的值和函数返回类型不一致,系统会自动将返回的值影式转换为函数的返回类型。

· return 语句执行后,函数就彻底返回,后边的代码不再执行。

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

6.数组做函数参数

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

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

基本函数形式如下:

#include <stdio.h>
int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	set_arr();//将数组的元素全部置为1
	print_arr();//打印数组的内容
	return 0;
}

补充几个重点知识:

1.函数的形参和函数的实参个数匹配;

2.函数的实参是数组,形参也可以写成数组形式;

3.形参如果是一维数组,数组的大小可以忽略不计;

4.形参如果是二维数组,行可以省略,但是列不能省略;

5.数组传参,形参是不会创建新的数组的;

6.形参操作的数组和实参的数组和实参的数组是同一个数组。

完整如下:

#include <stdio.h>
void set_arr(int arr2[], int sz2)
{
	for (int i = 0; i < sz2; i++)
	{
		arr2[i] = -1;
	}
}

void print_arr(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int sz1 = sizeof(arr1) / sizeof(arr1[0]);
	print_arr(arr1, sz1);
	set_arr(arr1,sz1);
	print_arr(arr1, sz1);
	return 0;
}

7.嵌套调用和链式访问

7.1 嵌套调用

嵌套调用就是函数之间互相调用,就像乐高积木一样,众多积木相互连接配合才能搭建出精美的成品,各个函数就像零件,函数间相互调用才能写出更大的程序。a函数调用了b函数,而b函数又调用了c函数,这就叫做嵌套调用。

假设现在需要计算某年某月有多少天,如下:

#include <stdio.h>
//一年的基本天数分别为31 28/29 31 30 31 30 31 31 30 31 30 31

int get_days_of_month (int y, int m)
{
	int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	int day = days[m];
	//闰年的二月是29
	if (leap_year(y) && m == 2)
	{
		day++;
	}
	return day;
}

int leap_year(int y)
{
	if ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0))
		return 1;
	else
		return 0;
}

int main()
{
	int year = 0;
	int month = 0;
	scanf("%d %d", &year, &month);
	int d = get_days_of_month(year, month);
	printf("%d", d);
	return 0;
}

7.2 链式访问 

链式访问指的是将一个函数的返回值作为另一个函数的参数,像链条一样将函数串联起来。上面的嵌套调用是在函数定义的时候调用一个函数。举例:

#include <stdio.h>
#include <string.h>
int main()
{
	//size_t len = strlen("abcdef");
	//printf("%d", len);
	printf("%d", strlen("abcdef"));
	return 0;
}

将 strlen 返回的值直接作为 printf 的参数,像链条一样引动。这里应用一个先前讲过的例子(详见http://t.csdnimg.cn/U2k4O):

#include <stdio.h>
int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	return 0;
}

输出结果为4321(注意:“ ”也是字符)。

8. 函数的声明和定义

8.1 单个文件

依然还是这个程序:

#include <stdio.h>
//一年的基本天数分别为31 28/29 31 30 31 30 31 31 30 31 30 31

//函数的定义
int get_days_of_month (int y, int m)
{
	int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	int day = days[m];
	//闰年的二月是29
	if (leap_year(y) && m == 2)
	{
		day++;
	}
	return day;
}

//函数的定义
int leap_year(int y)
{
	if ((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0))
		return 1;
	else
		return 0;
}

int main()
{
	int year = 0;
	int month = 0;
	scanf("%d %d", &year, &month);
	int d = get_days_of_month(year, month);//函数的调用
	printf("%d", d);
	return 0;
}

注意,在这里函数的定义是在函数的调用之前,没有警告或报错;如果将函数的定义移到函数调用之后,会这样(虽然还是可以运行):a32817b720c04362a16cfdc82bac95ce.png

所以,函数的使用一定要满足先声明再使用。 

8.2 多个文件

当代码较多的时候,不会将代码全部放在一个文件当中,往往根据程序的功能将代码拆分成多个文件。

一般地,我们将函数的声明、类型的声明放在头文件(.h)中,将函数的实现放在源文件(.c)中。

Add.c

函数的定义
int Add(int x, int y)
{
	return x + y;
}

Add.h

//函数的声明
int Add(int x, int y);

test.c

#include <stdio.h>
#include "Add.h"//自定义的函数头文件使用“”
int main()
{
	int a = 10;
	int b = 20;
    //函数调用
	int c = Add(a, b);
	printf("%d", c);
	return 0;
}

函数的相关知识先总结到这里(汗流浃背……),后续详见 C——函数(2)(努力学习ing)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YMLT花岗岩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值