C语言基础--函数(指针函数、函数指针、回调函数、递归函数)

函数

1. 函数的定义和声明

  • 1.函数定义

    <数据类型> <函数名称> (<形参列表>)
    {
        语句序列;
        return (<表达式> );
    }
    
  • 若缺省返回值类型则会默认为int型

  • 函数名即函数的入口地址

函数的声明

​ 即将函数的相关信息告诉编译器,如此才能使用函数。

  • 函数必须先声明才能使用

2. 函数的参数传递

  1. 值传递
    • 形参变量只有在被调用是才分配内存空间,调用结束即释放。
    • 实参和形参在数量、类型、书序上必须保证严格的一致,否则会发生类型不匹配的错误
    • 值传递的方式,不会影响实参的值。
  2. 地址传递方式
    • 地址传递的方式,被调用函数中可以改变实参的值。
  • 3.全局变量传参
    • 因为全局变量对所有函数可见,所以任何一个函数给变了全局变量都会对其他使用该全局变量的函数产生影响。

3. 函数的返回值

  • 函数的返回值只能通过return语句返回主调函数。
  • 函数返回值的类型应该与函数定义时的一致,否则会发生强制类型转换。
  • 缺省返回值类型为int
  • 函数的返回值不是由return返回去的,而是操作系统通过寄存器返回的,故return后可不跟参数。return可单独使用可用于终止程序的执行

4. 函数与数组

  • 1.传递数组

    当形参是数组形式时,本质是同级别的指针。如

    int fun(int a[],int *p,char a);
    等价于;
    int fun(int *q,int *p,char a);
    
  • 2.传递指针

    main函数的参数

  • 其实,main函数也可以带参数的,其参数是通过命令行传入,其形式如下:

    int main(int argc,char *argv[])
     也可以写为:
    int main(int argc,char **argv)
    

5. 指针函数

  • 若一个函数的返回值为一个指针,则这个函数就叫做指针函数

  • 指针函数返回的指针在主调函数中必须是有效的,否则会报错。

  • 指针函数不能返回局部指针变量。但可以返回static修饰的静态指针变量,因为局部变量存储在栈区,函数结束时就会释放,而静态变量存储在静态存储区,直到程序结束才会被被释放。

    如:下面这段代码中指针是不能被返回的,这样写是会报错的。

    char *fun(void)
    {
        char s[]={0};
        strcpy(s,"welcome");
        
        return s;
    }
    
  • 可以返回指向字符串常量的指针,因为字符串常量和静态变量类似,都是程序结束时,才释放内存,因此指针可以返回一个字符串常量的地址。如;

    char* fun(void)
    {
        char *str = "hello";
        return str;
    }
    
  • 指针函数可以返回一个堆区上面的空间,如:

    char *fun(void)
    {
        char *p = (char *)malloc(18);
        return p;
    }
    

总结:

​ 指针函数不可以返回局部变量的地址,可以返回一下三种情况:

  1. 静态变量的地址
  2. 字符串常量的地址
  3. 堆上的地址

6. 函数指针

  • 函数指针专门用来存放函数的地址

  • 函数指针的一半形式如下:

    <数据类型> (*<函数指针名称>)(<参数说明列表>);

    注意和指针函数的区别,括号的作用是使得*先和指针变量结合。

  • 函数指针的形式要与所指向的函数的形式保持一致。

    Linux内核中经常用到一下定义方法:

typedef <数据类型> (*<函数指针名称>) (<形参列表>)
  • 在函数指针变量说明前面加上typedef,就变成了函数指针类型。即声明了一个函数指针的数据类型。

函数指针数组:

  • 函数指针数组是一个包含若干个函数指针变量的数组。定义形式为:

    <数据类型> (*<函数指针数组名称> [<大小>]) (<参数说明列表>)
    

    即该数组中可以存放多个同一类型函数的地址。

    举一个函数指针的典型的例子,如内核中的信号注册函数。

    #include <signal.h>
    typedef void (*sighandler_t)(int);
    sighander_t signal(int signum,sighandler_t handler);
    

    看起来是不是特别奇妙,很有启发?

7. 递归函数

  1. 递归函数的定义

    • 所谓递归函数是指一个函数的函数体中直接或者间接调用了该函数自身。

      递归函数的调用的执行过程分为两个阶段:

      • 递推阶段:从原问题出发,按递归公式从未知到已知,最终达到递归终止条件。
      • 回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求解。

      注意:必须具有递归终止条件,否则会进入无限递归。

  2. 函数调用机制

    • 函数可以嵌套调用,但是不能嵌套定义。这是递归能够实现的理论基础。
  3. 递归调用的条件

    • 需有完成函数任务的语句
    • 递归终止条件
    • 一个递归调用语句
    • 先测试,后递归调用
  4. 回调函数

    • 就是一个通过函数指针调用的函数。

    回调函数的机制:

    1. 定义一个回调函数;
    2. 提供函数的一方在初始化的时候,将回调函数的函数指针注册给调用者
    3. 当特定时间发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值