C语言 - 函数

函数组成:

返回类型 函数名(函数参数)

{

        语句项

}

函数参数

实际参数:

真实传给函数的参数,可以是:常量、变量、表达式、函数等。在进行函数调用时,实参必须有确定值,把这些值传送给形参

形式参数:

形式参数是指函数名后括号中的变量,形式参数只有在函数被调用的过程中才实例化(分配内存单元),实例化后相当于实参的一份临时拷贝,当函数调用完成之后形式参数就自动销毁了

 

 

 

函数的调用

传值调用:

函数形参和实参地址不同,因此形参被修改并不会影响实参

传址调用:

把函数外部创建变量的地址传给函数参数,通过直接访问地址对变量进行修改,达到函数内部直接操作函数外部变量的效果

 

 代码:

#include<stdio.h>

void SwapV1(int ca, int cb)
{
	int temp = ca;
	ca = cb;
	cb = temp;
}

void SwapV2(int* pa, int* pb)
{
	int temp = *pa;
	*pa = *pb;
	*pb = temp;
}

int main()
{
	int a = 5;
	int b = 10;

	//传值调用
	SwapV1(a, b);
	printf("V1:a = %d,b = %d\n", a, b);

	//传址调用
	SwapV2(&a, &b);
	printf("V2:a = %d,b = %d\n", a, b);
	
	return 0;
}

运行结果:

 

嵌套调用

函数之间可以嵌套调用,即在函数内部调用其它函数,如上述代码中在main函数中调用Swap1,Swap2函数

注:函数之间可以嵌套调用但不可以嵌套定义

链式访问

把一个函数的返回值作为另一个函数的参数

有如下代码:

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

这里我们需要了解printf函数的返回值

如果成功,返回值是写入的字符总数

如果写入错误,设置错误指示器(ferror函数值为假),并返回一个负数

 运行结果:

 

函数声明

返回类型 函数名(函数参数);

函数参数可以只写参数类型,不写参数名

规定函数必须先声明后使用,但C语言中如果直接使用没声明也可以通过,但是会有警告

#include<stdio.h>

//int Add(int, int);

int main()
{
	int a = 10;
	int b = 5;
	int ret = Add(a, b);
	printf("%d\n", ret);
	return 0;
}

int Add(int a, int b)
{
	int z = a + b;
	return z;
}

函数声明一般放在头文件中,如果我们只想让他人知道函数如何使用,却不知道实现函数的源代码,方法如下:

 

此时文件路径下会生成一个.lib文件,这个文件是看不到源码的

 将add.h文件和Add.lib文件都给test

 添加现有项add.h文件到头文件,最后得到结果

 

函数递归

递归函数是直接或间接调用自身的函数

 递归的两个必要条件:(防止无限递归下去)

存在限制条件,当满足这个限制条件的时候,递归便不再继续

每次递归调用之后越来越接近这个限制条件

例:编写函数不允许创建临时变量,求字符串的长度

 

 代码如下:

#include<stdio.h>
int my_strlen(const char* str)
{
	if (*str == '\0')
	{
		return 0;
	}
	else return 1 + my_strlen(str + 1);
}
int main()
{
	char* p = "abcd";
	int len = my_strlen(p);
	printf("%d\n", len);
	return 0;
}

图解:

 递归与迭代

求第n个斐波那契数

递归:

#include<stdio.h>

int Fib(int n)
{
	if (n <= 2)
	{
		return 1;
	}
	else
	{
		return Fib(n - 2) + Fib(n - 1);
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", ret);
}

运行结果:

 

当计算第50个斐波那契数的时候,需要的时间就已经很长很长了,因为这种递归做法计算机需要进行很多重复计算,如我们递归到Fib(20)时,还需要向下计算Fib(19)+Fib(18),而每一个分支又要向下进行许多重复计算,显然计算斐波那契数时用递归不是很合适。

迭代:

 

#include<stdio.h>

long long Fib(int n)
{
	long long a = 1;
	long long b = 1;
	long long c = 1;
	//当n为1或2时,斐波那契数都为1
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}

int main()
{
	int n = 0;
	scanf("%d", &n);
	long long ret = Fib(n);
	printf("%lld\n", ret);
}

运行结果:

 

如阶乘,斐波那契等问题都有相应的递归公式,这种公式便于理解,然而事实上这些问题用递归可能并不是很合适,那么我们就需要迭代,用递归一定要保证没有错误的测试用例,如果不能保证,则不要使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值