C语言,函数调用机制

如何理解方法这个概念

给大家举个通俗的示例:

在这里插入图片描述

函数-调用过程

 为了更好的理解函数调用过程, 看两个案例,并画出示意图(机制),这个很重要 1) 传入一个数+1 test 函数
2)计算两个数,并返回 getSum 函数
3)对应示意图
在这里插入图片描述
在这里插入图片描述
4)函数调用规则 函数调用的规则(适用于 java, c++, php 等)
1, 当调用(执行)一个函数时,就会开辟一个独立的空间(栈)
2, 每个栈空间是相互独立
3,当函数执行完毕后,会返回到调用函数位置,继续执行
4,如果函数有返回值,则,将返回值赋给接收的变量
5, 当一个函数返回后,该函数对应的栈空间也就销毁

简单举例说明

在这里插入图片描述

函数-递归调用

一个函数在函数体内又调用了本身,我们称为递归调用

递归调用快速入门

在这里插入图片描述通过两个题,分析递归执行的流程和机制
在这里插入图片描述

函数递归需要遵守的重要原则

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

递归课堂练习题

斐波那契数 请使用递归的方式,求出斐波那契数 1,1,2,3,5,8,13… 给你一个整数 n,求出它的斐波那契数是多少?

#include<stdio.h>

int fbn(int i){
	if(i == 1 || i ==2 ) { 
		return 1; 
	} else { 
		return fbn(i-1) + fbn(i-2);
 	} 
}

void main(){
	int res = fbn(7); // res = 13 
	printf("\nres=%d", res);
}

求函数值 已知 f(1)=3; f(n) = 2*f(n-1)+1; 请使用递归的思想编程,求出 f(n)的值?

#include<stdio.h>

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


void main(){
	int res = f(7); // res = 255
	printf("\nres=%d", res);
}

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

#include<stdio.h>

//分析: 
// 1. day=10 有 1 个桃子 
// 2. day=9 有 (day10 + 1) * 2 = (1+1) * 2 = 4 
// 3. day=8 有 (day9 + 1) * 2 = (4+1) * 2 = 10 
int peach(int day) { 
	if(day == 10) { 
		return 1; 
	} else { 
		return (peach(day+1) + 1) * 2; 
	} 
}

void main(){
	int res = peach(1); // res = 1534
	printf("\nres=%d", res);
}

函数注意事项和细节讨论

1) 函数的形参列表可以是多个。
2)C 语言传递参数可以是值传递(pass by value),也可以传递指针(a pointer passed by value)也叫引用传递。
3) 函数的命名遵循标识符命名规范,首字母不能是数字,可以采用 驼峰法 或者 下划线法 ,比如 getMax() get_max()。
4) 函数中的变量是局部的,函数外不生效【案例说明】
5) 基本数据类型默认是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值。【案例演示】

//基本数据类型默认是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值
void f2(int n) { 
	n++; 
	printf("\nf2 中的 n=%d", n); // n=10 
}
void main() { 
//函数中的变量是局部的,函数外不生效 
	int n = 9; 	
	f2(n); 
	printf("\nmain 函数中 n=%d", n); //9 
}

6)如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果 上看类似引用(即传递指针) 【案例演示:】

//如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&, 
//函数内以指针的方式操作变量。从效果上看类似引用(即传递指针) 
void f3(int *p) { 
	(*p)++;// 修改会对函数外的变量有影响 
}

void main() { 
	//函数中的变量是局部的,函数外不生效 
	int n = 9; 
	f3(&n); 
	printf("\nmain 函数中 n=%d", n); 
}

7) C 语言 不支持函数重载。
8) C 语言支持可变参数函数 知道即可

#include <stdio.h> 
#include <stdarg.h> 

//说明 
//num 表示传递的参数格式 
//... 表示可以传递多个参数和 num 一致即可 

//可变函数,即参数的个数可以不确定, 使用... 表示 
int fun(int num, ...) {
	 int i, totalSum=0; //totalSum 一定要初始化 
	 int val = 0; 
	 va_list v1; //v1 实际是一个字符指针,从头文件里可以找到 
	 va_start(v1, num); //使 v1 指向可变列表中第一个值,即 num 后的第一个参数 
	 printf("*v = %d\n",*v1); 
	 for(i = 0; i < num; i++) {//num 减一是为了防止下标超限  
	 	val = va_arg(v1, int); //该函数返回 v1 指向的值,并使 v1 向下移动一个 int 的距离,使其指向下一个 int 
	 	printf("val = %d\n", val); // val = 10 val=30 val=60
		totalSum += val; 
	}
	va_end(v1); //关闭 v1 指针,使其指向 null return totalSum; 
}

void main() { 
	int res = fun(8, 10,30,60, -100,1,5,7,98); 
	printf("和是=%d", res); 
 }

课堂练习题: 请编写一个函数 swap(int *n1, int *n2) 可以交换 n1 和 n2 的值

#include<stdio.h>

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


void main(){

	int n1 = 1;
	int n2 = 2;
	swap(&n1,&n2);
	printf("main n1 = %d , n2 = %d",n1,n2); 
}

在这里插入图片描述
对上面代码的执行机制分析(重要)

在这里插入图片描述

结合上图再看引用传递

函数参数的传递方式

基本介绍

我们在讲解函数注意事项和使用细节时,已经讲过 C 语言传递参数可以是值传递(pass by value),也可以传递指 针(a pointer passed by value)也叫传递地址或者 引用传递。

两种传递方式

1)值传递
2)引用传递(传递指针、地址)
其实,不管是值传递还是引用传递,传递给函数的都是变量的副本,不同的是,值传递的是值的拷贝,引用传递的是地址的拷贝,一般来说,地址拷贝效率高,因为数据量小,而值拷贝决定拷贝的数据大小,数据越大,效率 越低。

值传递和引用传递使用特点:

1)值传递:变量直接存储值,内存通常在栈分配
2)默认的值传递数据类型有,基本数据类型,结构体,共用体,枚举类型
在这里插入图片描述

3)引用传递:变量存储的是一个地址,这个地址对应的空间才是真正存储的数据(值)
4)默认是引用传递的数据类型,有指针和数组

在这里插入图片描述
5)如果希望函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量(*指针)。 从效果上看类似引用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值