一、函数的调用机制

(一)、调用机制:程序员调用方法,方法给程序员返回结果

举例:
(1)传入一个数+1 test函数

//第一题
#include<stdio.h>

int test(int n1){
	int sum = n1 + 1;
	printf("sum = %d",sum);
	return 0;
}

void main(){
	int n2=6;
	test(n2);
}

在这里插入图片描述
(2)计算2个数并返回 getSum函数

//第二题
#include<stdio.h>

int getSum(int n1,int n2){
	return n1+n2;
}

void main(){
	int res=getSum(1,9);//传入1 和 9 
	printf("\nres = %d",res);// res = 10
}

在这里插入图片描述

(二)、函数调用规则

1.当调用(执行)一个函数时,就会开辟一个独立的空间(栈)。
2.每个栈空间是相互独立
3.当函数执行完毕后,会返回到调用函数位置,继续执行。
4如果函数有返回值,则将返回值赋给接收的变量。
5.当一个函数返回后,该函数对应的栈空间也就销毁

举例:判断函数调用是否正确。

案例1

char* getSum(int num1,int num2){
	int res = num1 + num2;
	retuen res; 
}

错误原因是类型不匹配(char* 到 int)。

案例2

int getSum(int num1,int num2){
	int res = num1 + num2;
	retuen res; 
}

正确,int 到 int。

案例3

int getSum(int num1,int num2){
	int res = num1 + num2;
	retuen 0.0; 
}

可以运行,但是会有警告 double 到 int 有精度损失。

案例4

int getSum(int num1,int num2){
	int res = num1 + num2;
	retuen (int)0.0; 
}

正确,因为有强制转换

案例5

double getSum(int num1,int num2){
	int res = num1 + num2;
	retuen res; 
}

正确,精度小的转精度大的自动转换。

二、函数的递归调用

(一)、递归调用:一个函数在函数体内又调用了本身。

案例:在一个函数在函数体内又调用了本身。

#include<stdio.h>

void test(int n){
	if(n>2){
		test(n-1);
		printf("n=%d\n",n);
	}
}

void main(){

	test(9);
}

在这里插入图片描述

(二)、函数递归需要遵守的重要原则

(1)执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)。
(2)函数的局部变量是独立的,不会相互影响。
(3)递归必须向退出递归的条件逼近,否则就是无限递归。
(4)当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁。

递归练习题

1.斐波那契数

请使用递归的方式,求出斐波那契数1,1,2,3,5,8,13…
给你一个整数n,求出它的斐波那契数是多少。(比如输入7,输出13)

分析:第1,2个数输出1,第3个=第2个+第1个数,…,第n个=第n-1 +第n-2。

#include<stdio.h>

int test(int n){
	if(n==1 || n==2){
		return 1;
	}
	else{
		return test(n-1) + test(n-2);
	}
}

void main(){
	int m;
	scanf("%d",&m);
	int res = test(m);
	printf("\nres = %d",res);
}

在这里插入图片描述

2.求函数值

己知 f(1)=3;f(n)= 2*f(n-1)+1;请使用递归的思想编程,求出f(n)的值。(比如输入15,输出65535)

#include<stdio.h>

int test(int n){
	if(n==1){
		return 3;
	}
	else{
		return 2*test(n-1) + 1;
	}
}

void main(){
	int m;
	scanf("%d",&m);
	int res = test(m);
	printf("\nres = %d",res);
}

在这里插入图片描述

3.猴子吃桃问题

有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!以后每天猴子都吃其中的一半,然后再多吃一个。当到第十天时,想再吃时(还没吃),发现只有1个桃子了。问题:最初共多少个桃子。

分析:
day=10,1个桃子。
day=9, (day10+1)*2 = (1+1)*2=4
day=8,(day9+1)*2 =(4+1)*2=10

#include<stdio.h>

int test(int day){
	if(day==10){
		return 1;
	}
	else{
		return (test(day+1) + 1)*2;
	}
}

void main(){
	int m;
	scanf("%d",&m);
	int res = test(m);
	printf("\nres = %d",res);
}

在这里插入图片描述

三、函数注意事项和细节讨论

(1)函数的形参列表可以是多个。
(2)C语言传递参数可以是值传递〈pass by value),也可以传递指针(a pointer passed by value)也叫引用传递。
(3)函数的命名遵循标识符命名规范,首字母不能是数字,可以采用驼峰法或者下划线法,比如getMax()。
(4)函数中的变量是局部的,函数外不生效。

#include<stdio.h>

void f1(int n){
	n++;//函数中的变量是局部的,函数外不生效。
	printf("\nf1中的 n=%d",n);//函数中的是 10 
} 

void main(){
	int n = 9;//还是 9 
	f1(n);
	printf("\nmain中 n=%d",n);
}

在这里插入图片描述
(5)基本数据类型默认是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值。(如上面例子)
(6)如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用(即指针传递)。

#include<stdio.h>

void f1(int*n){
	(*n)++;
} 

void main(){
	int n = 9;
	f1(&n);
	printf("\nmain中 n=%d",n);//10
}

在这里插入图片描述
(7)C语言不支持函数重载。
(8)C语言支持可变参数函数。

习题

请编写一个函数swap(int nl, intn2)可以交换nl 和 n2的值。

#include<stdio.h>

void swap(int*n1,int*n2){
	int temp = *n1;//将 n1 这个指针指向的变量赋值给 temp
	*n1 = *n2;
	*n2 = temp; 
}

void main(){
	int n1=10,n2=20;
	swap(&n1,&n2);
	printf("n1=%d n2=%d",n1,n2);
}

在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐