韩顺平-函数

函数

基本语法

返回类型 函数名(形参列表)
{
执行语句;
返回值}

#include <stdio.h>
double cal(int n1,int n2,char oper){
    double res = 0.0f;//定义一个变量接收返回值
    switch(oper){
        case '+':
         res = n1 + n2;
         break;
        case '-':
         res = n1 - n2;
         break;
        case '*':
         res = n1 * n2;
         break;
        case '/':
         res = n1 / n2;
         break;
        default:
            printf("请输入四则运算符");
    }
    printf("%d %c %d = %f\n",n1, oper, n2, res);
}
int main(void) {
    cal(3,2,'/');
    printf("%f",3.0f/2.0f);
    return 0;
}


头文件

头文件里包含了声明和宏定义,被多个源文件引用共享,不同的文件里定义了不同的函数,在头文件中声明函数,在源文件中定义函数
可以把所有的常量,宏,系统全局变量,函数原型写在头文件中

  1. 标准库提供
  2. 自己写
    使用头文件中声明的函数
    #include<>引用系统头文件,是在系统的目录下方寻找,效率更高
    #include“ ”:可以引用系统头文件和自己的头文件,会在编译器指定的目录下寻找。
    多次引用头文件不会报错,因为有代码防重复机制。
    头文件只能包含函数的声明,不能包含定义

调用机制

程序执行到主函数时,计算机会在栈中开辟一个独立的空间:main栈,在栈中有了独立的变量,当执行main函数中自定义的函数时,栈中会开辟另一个独立的空间,函数栈(开辟了新栈)。在新的栈中执行相应语句,执行完(或者遇到return语句)后重新返回到main栈中函数所在的位置,继续执行,为函数开辟的栈被销毁。如果函数有返回值,就把此值返回给接收的变量。
转换数据类型的方法(int)n
每个栈空间是独立不冲突的

递归调用

递归调用时,当最后一个调用停止时,函数会返回一个值,此栈被销毁,转到上一个调用的地方,此时返回的值是上一个调用的n值,因为下一个栈已经被销毁
函数的栈都是相互独立的,不影响
递归条件必须向退出递归的条件逼近,都则会发生栈溢出
斐波那契数列

#include <stdio.h>
int fnb(int n){
    if(n==1||n==2){
        return 1;
    }
    else{
        return fnb(n-1) + fnb(n-2);
    }
}
int main(void) {
    int num = 2;
    num = fnb(num);
    printf("n = %d\n", num);
    return 0;
}

猴子吃桃:有一堆桃子,猴子第一天吃了其中的一半,又吃了一个,以后猴子每天这样吃,在第10天去吃时发现还剩一个桃子,问原来有多少桃子

#include <stdio.h>
int fn(int n){
    if(n==10){
        return 1;
    }
    else{
        return 2*(fn(n+1) + 1);
    }
}
int main(void) {
    int num = 1;
    num = fn(num);
    printf("n = %d\n", num);
    return 0;
}

参数传递

如果想要函数内的变量影响到函数外的变量,使用指针传递
f(&n):&n取的是n变量的地址,函数参数进行接收时int *p
p中是地址,*p取的是p指针指向的变量,即使栈销毁了,但改变的是main栈中的值。
不支持函数重载不能通过参数的个数不同或类型不同来区分函数。
支持可变参数

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

int fun(int num, ...)//可变函数,即参数的个数可以不确定,使用三个点表示
{
    int i, totalSum = 0;
    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("res = %d\n", val);
        totalSum += val;
    }
    va_end(v1);//关闭v1指针,使其指向null
    return totalSum;
}
void main() {
    fun(3, 30, 20, 11);//在3后面需要输入3个数
    printf("%d", res);
}
传递指针(引用传递)
#include <stdio.h>
//编写一个函数,可以交换n1,n2: swap(int *n1, int *n2)
void swap1(int* n1, int* n2) {//在为swap函数开辟的栈中,n1,n2在swap中有自己的地址,只是n1,n2保存的是在main栈中n1,n2的具体地址
	int temp = *n1;//把n1指针指向的变量值赋给temp变量,*代表解析,取在swap栈中n1保存的地址对应的值
	*n1 =  *n2;//n1指针在上一步操作后没有值,所以接下来把n2指针指向的变量值赋给n1这个指针指向的变量
	*n2 = temp;//把ntemp变量指向的值值赋给n2这个指针指向的变量
}
void swap2(int n1, int n2) {//在为swap函数开辟的栈中,n1,n2在swap中有自己的地址,只是n1,n2保存的是在main栈中n1,n2的具体地址
	int temp = n1;//把n1指针指向的变量值赋给temp变量,*代表解析,取在swap栈中n1保存的地址对应的值
	n1 = n2;//n1指针在上一步操作后没有值,所以接下来把n2指针指向的变量值赋给n1这个指针指向的变量
	n2 = temp;//把ntemp变量指向的值值赋给n2这个指针指向的变量
}
void main() {
	int n1 = 1;
	int n2 = 2;
	swap2(n1, n2);//传递参数时传递的是n1,n2在栈中的地址
	printf("n1 = %d, n2 = %d\n", n1, n2);
	swap1(&n1, &n2);//传递参数时传递的是n1,n2在栈中的地址
	printf("n1 = %d, n2 = %d", n1, n2);	
}

不管是值传递还是引用传递,传递都是变量的副本,只不过值传递传递的是值的拷贝,而引用传递传递的是地址的拷贝,地址拷贝效率高,因为数据量小,值拷贝取决于拷贝数据的大小,数据越大,下效率越低。
引用传递的类型有:数组,指针

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值