C语言——指针与函数

指针与函数

用指针作为函数的参数


引:函数参数可以为 intcharfloat 等,这些参数只作为形参,所有操作都只在函数体内有效(除对指针的操作外)

一、传递指针给函数

  1. 传递普通(如int)型指针给函数

    //通过函数将x,y进行值的转换
        
    void swap(int *x, int *y);
    void main()
    {
           int x = 20, y = 10;
           swap(&x, &y);
           printf("x = %d, y = %d", x ,y);
    }
    
    void swap(int *x, int *y)
    {
           int t;
           t = *x;
           *x = *y;
           *y = t;
    }
    //结果:x = 10, y = 20
    

    用指针作为函数参数,函数内改变被指针指向变量的值,在函数外值也会的改变。

  2. 传递指针数组给函数

    //通过函数求数组元素之和
    
    #include <stdio.h>
    
    int sum(int *arr);
    
    int main()
    {
        int num[5] = {1000, 2, 3, 17, 50};
        int a;
        a = sum( num ) ;
        printf("sum is: %d\n", a );
        return 0;
    }
    
    int sum(int *arr)
    {
        int i, b = 0;
        for (i = 0; i < 5; i++)
        {
        	b += arr[i];
        }
    	return b;
    }
    

    在这里插入图片描述

二、从函数返回指针

  1. 返回值为指针的函数声明

    数据类型 *函数名(参数列表)
    {
    	 函数体
    }
    

    例:

    int s;
    void mian()
    {
    	int *r = sum(10, 9);
    	printf("10 + 9 + %d", *r);
    }
    
    int *sum(int x, int y)
    {
    	s = x + y;
    	return &s;
    }
    

    注意
    C 语言不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量。
    函数返回指针用于返回一个指向数组的指针,这样就实现了返回值为数组。

  2. 返回指向数组的指针的函数例题
    生成 10 个随机数,并使用表示指针的数组名来返回它们

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h> 
     
    int *getRandom( )
    {
       static int  r[10];
       int i;
     
       srand( (unsigned)time( NULL ) );
       for ( i = 0; i < 10; ++i)
       {
          r[i] = rand( );
       }
       return r;    //第一个数组元素的地址
    }
     
    int main ()
    {
       
       int *p;
       int i;
       **p = getRandom( );    //返回指向数组的指针**
       for ( i = 0; i < 10; i++ )
       {
           printf("*(p + [%d]) : %d\n", i, *(p + i) );
       }
     
       return 0;
    }
    

三、指向函数的指针

一个函数在编译之后,会占据一部分内存,而它的函数名,就是这段函数的入口地址.

可以把一个指针,声明成为一个指向函数的指针,将指针作为参数传递。


  1. 定义

    数据类型 (*函数指针名)();
    typedef int (*fun_ptr)(int,int);	 // 声明一个指向同样参数、返回值的函数指针类型
    

    注意事项

    函数指针在进行“*”操作时,可以理解为执行该函数
    函数的调用:(*p)(x, y);

    int a=(*pfun)(5,7);
    

    函数名会自动认为指向这个函数的指针
    两种形式:函数指针名 = 函数名; 函数指针名 = &函数名

    int fun(int a, int b)
    {
        return a+b;
    }
    int main()
    {
        int (*pfun)(int,int);
        pfun = fun;
        int a = (*pfun)(5,7); 
    }
    

    指向函数的指针必须初始化,或者具有 0 值,才能在函数调用中使用
    禁止对指向函数的指针进行自增运算++
    禁止对函数名赋值,函数名也不能用于进行算术运算
    *函数名 --> *(&函数名) --> 函数名 --> &函数名

    //在使用中函数名会被转换为指向这个函数的指针
    
    int a(int m, int n)
    {
           return m+n;
    }
    
    void main()
    {
    	a(1,2);
    	printf("%p",*a);
    }
    
    //结果:0000000000401530
    
  2. 例题——比较三个数大小

    #include <stdio.h>
    
    int max(int x, int y)
    {
        return x > y ? x : y;
    }
     
    int main(void)
    {
        int (* p)(int, int) = & max; // &可以省略
        int a, b, c, d;
     
        printf("请输入三个数字:");
        scanf("%d %d %d", &a, &b, &c);
     
        /* 与直接调用函数等价,d = max(max(a, b), c) */
        d = p(p(a, b), c); 
     
        printf("最大的数字是: %d\n", d);
     
        return 0;
    }
    

四、回调函数

函数指针作为某个函数的参数

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


  1. 解释

    你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。

    你的电话号码就叫回调函数,电话叫函数指针,

    你把电话留给店员就叫登记回调函数,

    店里后来有货了叫做触发了回调关联的事件,

    店员给你打电话叫做调用回调函数,

    你到店里去取货叫做响应回调事件。

    如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。

  2. 实例分析

    fun函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。

    #include <stdlib.h>
    #include <stdio.h>
    
    // 回调函数
    void fun( int *arr,  int arrSize,  int (*pRandom)(void) )
    {
            int i;
            for(i=0; i<arrSize; i++)
            {
                *(arr+i) = pRandom();    //将函数的值赋给数组
            }
    }
    
    // 获取随机值
    int random(void)
    {
          return rand();
    }
    
    int main(void)
    {
          int myarr[10];
          int i;
          fun(myarr, 10, random);
          for(i=0; i<10; i++)
          {
               printf("%d\\n", myarr[i]);
          }
    
    }
    
  3. 优点

    1)解耦: 在主入口程序中,把回调函数像参数一样传入库函数。这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,且不需要修改库函数的实现,变的很灵活。

    2)主函数和回调函数是在同一层的,而库函数在另外一层。 如果库函数对我们不可见,我们修改不了库函数的实现,也就是说不能通过修改库函数让库函数调用普通函数那样实现,那我们就只能通过传入不同的回调函数了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值