一、函数的调用机制
(一)、调用机制:程序员调用方法,方法给程序员返回结果
举例: (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, int n2)可以交换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); } 复制代码