C语言函数

1. 函数的概念
数学中我们其实就⻅过函数的概念,⽐如:⼀次函数 y=kx+b ,k和b都是常数,给⼀个任意的x,就得到⼀个y值。其实在C语⾔也引⼊函数(function)的概念,有些翻译为:⼦程序,⼦程序这种翻译更加准确⼀些。C语⾔中的函数就是⼀个完成某项特定的任务的⼀⼩段代码。这段代码是有特殊的写法和调⽤⽅法的。C语⾔的程序其实是由⽆数个⼩的函数组合⽽成的,也可以说:⼀个⼤的计算任务可以分解成若⼲个较⼩的函数(对应较⼩的任务)完成。同时⼀个函数如果能完成某项特定任务的话,这个函数也是可以复⽤的,提升了开发软件的效率。
C语言中的函数分为两类:
  1.库函数
  2.自定义函数
2. 库函数
C语⾔标准中规定了C语⾔的各种语法规则,C语⾔并不提供库函数;C语⾔的国际标准ANSI C规定了⼀些常⽤的函数的标准,被称为标准库,那不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列函数的实现。这些函数就被称为库函数。 我们使用的scanf和printf就是库函数, 库函数也是函数,不过这些函数已经是现成的,我们只要学会就能直接使⽤了。有了库函数,⼀些常⻅的功能就不需要程序员⾃⼰实现了,⼀定程度提升了效率;同时库函数的质量和执⾏效率上都更有保证。各种编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头⽂件中进⾏了声明。
例如scanf和printf函数就需要引用头文件stdio.h。
2.2 库函数的使用
比如给出平方根函数sqrt
double sqrt(double x)

第一个double表示该函数的返回值的类型,sqrt是该函数的函数名,第二个double表示该函数参数的类型,x是该函数的一个参数。

sqrt函数的使用需要引用头文件math.h,实现代码如下:

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

代码结果为b的值,也就是4.000000。

3. 自定义函数
了解了库函数,我们的关注度应该聚焦在⾃定义函数上,⾃定义函数其实更加重要,也能给程序员写代码更多的创造性。
自定义函数的格式如下:
type name(形式参数)
{
    
}

type是该自定义函数的返回值类型,有时候函数可能没有返回值,那此时返回值类型为void。

name为该自定义函数的名字,可以随便起,但最好与该函数符合,容易理解。

函数的参数也要有类型,当参数的类型不确定时可以使其类型为void类型,此时传入函数的数据类型就是该函数参数的类型。而当函数没有参数时,可以在()内写void,表示该函数的参数为空。

在{}内的代码就是函数体,函数体就是函数的执行过程。

介绍完了自定义函数,我们可以试着来写一个加法函数。

#include<stdio.h>
int add(int x,int y)
{
    return x+y;    
}
int main()
{
    int a=3;
    int b=5;
    int sum=add(a,b);
    printf("%d",sum);
    return 0;    
}
代码结果就是ab的和,也就是8
函数的参数部分需要交代清楚:参数个数,每个参数的类型是啥,形参的名字叫啥。
上⾯只是⼀个例⼦,未来我们是根据实际需要来设计函数,函数名、参数、返回类型都是可以灵活变化的。
4. 形参和实参
在函数使⽤的过程中,把函数的参数分为,实参和形参。
为什么叫形式参数呢?实际上,如果只是定义了 Add 函数,⽽不去调⽤的话, Add 函数的参数 x
y 只是形式上存在的,不会向内存申请空间,不会真实存在的,所以叫形式参数。形式参数只有在函数被调⽤的过程中为了存放实参传递过来的值,才向内存申请空间,这个过程就是形参的实例化。而在函数调用时传递给函数的参数称为实参,实际参数就是真实传递给函数的参数。
既然形参是实参传递给函数得来的,那么实参与形参有什么关系呢?
实际上,实参与形参在内存中分别占有独立的内存空间。我们可以通过调试的方式来仔细观察二者间的关系。
可以看出,形参的地址与实参地址并不相同,且形参只有在函数调用时才会在内存中创建内存,所以我们可以理解为形参是实参的一份临时拷贝。
5. return语句

在函数中,我们经常可以看见return的语句,对于return语句来说,有许多需要注意的:

1. return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执⾏表达式,再返回表达式的结果。

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

3. return返回的值和函数返回类型不⼀致,系统会⾃动将返回的值隐式转换为函数的返回类型。

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

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

6. 数组作为函数参数

在我们使用函数时,避免不了把数组作为函数的参数来对数组进行一系列操作,而我们要对整个数组进行操作,就要知道数组的元素个数,所以数组传参的同时常常还要把数组的元素个数作为一个参数。

比如说我们想让一个数组通过函数进行初始化并打印,在写代码之前,我们要了解一下数组传参的知识:

1. 函数的形式参数要和函数的实参个数匹配
2. 函数的实参是数组,形参也是可以写成数组形式的
3. 形参如果是⼀维数组,数组⼤⼩可以省略不写
4. 形参如果是⼆维数组,⾏可以省略,但是列不能省略
5. 数组传参,形参是不会创建新的数组的
6. 形参操作的数组和实参的数组是同⼀个数组
以下是数组初始化和打印的函数:
#include<stdio.h>
void test(int str[], int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		str[i] = i;
	}
	for (i = 0; i < n; i++)
	{
		printf("%d ", str[i]);
	}
}
int main()
{
	int a[10] = { 0 };
	int sz = sizeof(a) / sizeof(a[0]);
	test(a, sz);
	return 0;
}

                               

此代码执行后数组的每个元素获得与其下标相同的值,在此之后,我们可以使用函数对数组进行操作了。

7. 函数的嵌套调用

在函数的使用过程中,总会遇到某些问题需要许多函数同时进行,函数的嵌套调用就是函数间的相互调用。

比如我们想求某年某月有多少天,首先要判断这一年是不是闰年,其次我们还要判断这一个月是不是2月。

#include<stdio.h>
int leap_year(int a)
{
	if (((a % 4 == 0) && (a % 100 != 0)) || (a % 400 == 0))
	{
		return 1;
	}
	return  0;
}
int get_days(int a, int b)
{
	int a[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int days = a[b];
	if (leap_year(a) && b == 2)
	{
		days++;
	}
	return days;
}
int main()
{
	int year = 0;
	int month = 0;
	scanf("%d %d", &year, &month);
	int day=get_days(year, month);
	printf("第%d年第%d月有%d天\n", year, month, day);
	return 0;
}

leap_year函数用来判断是不是闰年,get_days用来计算这一年这一个月有多少天。

对于不同的函数来说,可以进行嵌套调用,但是不能嵌套定义。

8. 函数的链式访问
所谓链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数,像链条⼀样将函数串起来就是函数的链式访问。
#include<stdio.h>
#include<string.h>
int main()
{
	char c[] = { "abcdef" };
	int len = strlen(c);
	printf("%d\n", len);
	printf("%d\n", strlen(c));
	return 0;
}

第一个printf打印的是len的值,而第二个printf则是以strlen函数的返回值作为参数,此时就是函数的链式访问。

那么下面代码的打印结果应该是什么呢?

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

对于printf函数来说,它的返回值是打印的字符个数,最内层的printf打印43,是2个字符,返回值为2,所以第二次打印2,第二个printf函数的返回值就为1,所以第三次打印1,最终结果为4321。

9. 函数的声明和定义

最后,我们再来介绍一下函数的声明与定义。对于一个函数来说,它的声明一定要在函数调用之前,因为在函数调用前要让系统知道这一串代码是函数才能不会报错。

通常我们将函数的声明写在程序前面,函数的声明形式如下:

type name(形式参数)

对于函数的定义,定义既可以在主函数之前,又可在主函数之后。那么,为什么定义在主函数之前时没有了函数声明呢?

事实上,函数的定义是一种特殊的声明。

本章C语言函数的介绍,完。

  • 41
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值