0
点赞
收藏
分享

微信扫一扫

【C语言】函数进阶

前面我已经写过一篇有关C语言初阶函数的博客,讲解了C语言中函数的基础知识。这篇博客我会总结一下前面已经讲解过的内容,并作适当拓展。

函数就是子程序,也就是一段代码用于完成一项特定的功能。函数分为库函数和自定义函数。库函数可以理解为C语言自带的函数(其实准确的说是C语言语法规定了一些函数的功能,然后由编译器实现)。使用库函数必须包含对应的头文件。

自定义函数是由程序员自己来写的函数,包含函数名,返回值类型,函数参数。

举个例子。写一个函数返回两个整数的较大值。

首先写出主函数:

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int ret = get_max(a, b);
	printf("%d\n", ret);

	return 0;
}

这里我们输入两个值存入a,b两个变量中,然后用get_max函数找到较大值,返回这个较大值后用ret接收,然后输出在屏幕上。接着写这个get_max函数。

int get_max(int x, int y)
{
	return x > y ? x : y;
}

关于x>y?x:y的讲解,我在前面讲解操作符的博客中有提到,作用是求出x和y的较大值。在这个函数中,get_max是函数名,函数名后面跟的括号里面写的是函数传的参数,这里我们要传递的是两个整数,函数名前面的int是返回值类型,由于返回的是两个整数的较大值,也是整数,所以写的int。

这里a和b叫做实参,x和y叫做形参,简单来说,定义函数时括号里的叫做形参(x和y),调用函数时括号里的叫做实参(a和b)。

这个函数比较简单,我相信看过我对函数初阶讲解的朋友都能很容易写出来。接下来讲个复杂点的,用函数交换两个整型变量。这个问题看似简单,但很多朋友第一遍都写不对。请你仔细看看我下面的写法有什么问题。

先写出主函数:

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d b=%d\n", a, b);
	Swap(a, b);
	printf("交换后:a=%d b=%d\n", a, b);

	return 0;
}

接着写出Swap函数:

void Swap(int x, int y)
{
	int tmp = x;
	x = y;
	y = tmp;
}

看出问题了吗?如果没有看出来,我们先运行一下: 

有没有发现,a和b压根就没有交换?

我们想要这个函数实现交换变量的功能,但是它却没按照我们的意思进行。这说明中间有猫腻!这时我们就要通过调试来找到错误。由于篇幅有限,我会在后面专门出一期博客讲解如何调试,这里就直接分析代码。

我们在主函数中创建了a和b两个变量,并且输入了3和5,此时a是3,b是5,此时我们调用Swap函数,把a中的3传给了x,把b中的5传给了y,此时x是3,y是5。注意了!a和b,x和y是完全不同的几块空间!我们这时在函数中交换了x和y的值,对a和b完全没有任何影响!所以这么写是错误的。

在调用这个Swap函数时,我们把a和b的值传递给了函数,这种函数调用方法被称为传值调用。传值调用时,函数形参是实参的一份临时拷贝,改变形参不影响实参!

那正确的写法是什么呢?

这时指针就要派上用场了。只要把所有传值部分改成地址就行了。写法如下:

void Swap(int* px, int* py)
{
	int tmp = *px;
	*px = *py;
	*py = tmp;
}

int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d b=%d\n", a, b);
	Swap(&a, &b);
	printf("交换后:a=%d b=%d\n", a, b);

	return 0;
}

运行结果: 

为什么传递指针就可以了呢? 

因为我们把a和b的地址传给了Swap函数,px就指向了a,py就指向了b,我们就能在Swap函数内部找到a和b所在的内存空间,也就能操作a和b的值了!

这种传递地址的调用方式叫做传址调用。传址调用时,函数可以建立形参和实参之间的联系,可以真正的通过形参找到实参,从而改变实参的值。

也就是说,当我们不需要改变实参的值时采取传值调用,如果需要改变实参的值则采取传址调用。

关于函数还有一些比较简单的知识,这里稍稍总结一下。

在一个函数内部调用另一个函数,叫做函数的嵌套调用。这里需要注意,函数可以嵌套调用,但不能嵌套定义!

把一个函数的返回值作为另一个函数的参数,叫做函数的链式访问。

函数的声明是告诉编译器函数名,参数类型和返回值类型。比如上面Swap函数的声明如下:

void Swap(int* x, int* y);

函数声明时,形参名可以省略。所以也可以这么写: 

void Swap(int*, int*);

函数的定义就是正常的实现函数的具体功能。

函数一定要先声明再使用!函数的声明一般包含在头文件中。

最后还有一块很重要的知识,就是函数的递归。我会放在之后的博客中讲解。

感谢你的阅读,喜欢的话就点个赞吧! 

 

 

 

举报

相关推荐

0 条评论