#c语言学习13—指针进阶2

6. 函数指针数组
7. 指向函数指针数组的指针
8. 回调函数
9. 指针和数组面试题的解析

函数指针数组

指针数组,本质上是一个数组,数组里存放的内容是指针变量
int* p[5]={&a,&b,&c};

函数指针,是一个指针,指针指向了函数名称(函数地址)
int Add( int x, int y )
{
int z=x+y;
return z;
}
int main()
{
int (*p)( int , int )=Add
}

当有多个函数需要存放其地址时,就需要函数指针数组

int Add( int x, int y )
{
   int z=x+y;
   return z;
}
int Sub( int x, int y )
{
   int z=x-y;
   return z;
}
int Mul( int x, int y )
{
   int z=x*y;
   return z;
}
int Div( int x, int y )
{
   int z=x/y;
   return z;
}

switch实现

int main() 
{
    int x, y, input;
    do
    {
        memu();
        printf("请输入您的选择->\n");
        scanf("%d", &input);
      switch(input)
     {
       case 1:
         printf("请输入您的操作数\n");
         scanf("%d%d", &x, &y);
         printf("%d",Add(x,y));
       break;
       case 2:
         printf("请输入您的操作数\n");
         scanf("%d%d", &x, &y);
         printf("%d",Sub(x,y));
       break;
       case 3:
         printf("请输入您的操作数\n");
         scanf("%d%d", &x, &y);
         printf("%d",Mul(x,y));
       break;
       case 4:
         printf("请输入您的操作数\n");
         scanf("%d%d", &x, &y);
         printf("%d",Div(x,y));
       break;
       case 0:
         printf("退出成功\n");
       breakdefaultprintf("请重新选择\n");
       
     }
    }while(input)
    
    return 0;
}

函数指针用途:转移表

通过函数指针数组实现,减少了代码的冗余情况,而且后期更加便于维护

int main()//转移表实现
{
    int x, y, input;
    int(*pfun[5])(int,int) = {0,Add,Sub,Mul,Div};
    do
    {
        memu();
        printf("请输入您的选择->\n");
        scanf("%d", &input);
        if (input >= 1 && input <= 4)
        {
            printf("请输入您的操作数\n");
            scanf("%d%d", &x, &y);
            int ret = pfun[input](x, y);
            printf("%d\n", ret);
        }
        else if (input == 0)
        {
            printf("退出成功\n");
        }
        else
        {
            printf("请重新选择\n");
        }

    } while (input);
    return 0;
}

回调函数

回调函数就是通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的方式直接调用,而是由另一方调用的。

利用回调函数也可以解决上述代码冗余的问题

void Calculator(int (*pfun)(int,int))
{
    printf("请输入您的操作数\n");
    scanf("%d%d", &x, &y);
    printf("%d",pfun(x,y));
}
int main() 
{
    int x, y, input;
    do
    {
        memu();
        printf("请输入您的选择->\n");
        scanf("%d", &input);
      switch(input)
     {
       case 1:
         Calculator(Add);
       break;
       case 2:
         Calculator(Sub);
       break;
       case 3:
         Calculator(Mul);
       break;
       case 4:
         Calculator(Div);
       break;
       case 0:
         printf("退出成功\n");
       breakdefaultprintf("请重新选择\n");
       
     }
    }while(input)
    
    return 0;
}

回调函数的补充使用实例

void print(char* str)
{
  printf("&s",str);
}
void test(void (*p)(char*))
{
  printf("test\n");
  p("abc");
}
int main()
{
  test(print);
  return 0;
}

指向函数指针数组的指针

创建一个指针,它指向数组数组是函数指针数组,所以指针是数组指针

int main()

{
  int arr[4]={0};
  int* parr[4]=&arr;//对于数组来说,创建一个数组指针
  
  int (*pFun)(int,int)=Add;
  int (*pFun[4])(int ,int)={Add,Sub,Mul,Div}//创建一个函数指针数组来存放函数地址,其本质还是一个数组,因此也可以再创建一个数组指针,来存放这个(函数指针)数组
  int(* (*ppFun)[4])(int, int)=&pFun
  

}

面试题解析

题目一

int main()
{
    int arr[] = { 1,2,3,4,5 };
    
    printf("%d\n", sizeof(arr));//20 sizeof(数组名)计算的整个数组的空间字节
    printf("%d\n", sizeof(arr+0));//4,当arr做加减运算时,我们把数组名看成了首地址,arr+0=&arr[9]
    printf("%d\n", sizeof(*arr));//4 相当于取出首地址内存储的内容并计算其字节大小
    printf("%d\n", sizeof(arr+1));//4
    printf("%d\n", sizeof(arr[1]));//4
    printf("%d\n", sizeof(&arr));//4/8 &arr是数组地址,所以求的是数组地址的大小
    printf("%d\n", sizeof(*&arr));//20 &arr是数组地址 *&arr是将整个数组取出并计算大小
    printf("%d\n", sizeof(&arr+1));//4/8 &arr+1其实还是一个地址
    printf("%d\n", sizeof(&arr[0]));//4/8
    printf("%d\n", sizeof(&arr[0]+1));//4/8
    return 0;
}

题目二

 char arr[] = {'a','b','c','d'};
    printf("%d\n",sizeof(arr));//4
    printf("%d\n", sizeof(arr+0));//1
    printf("%d\n", sizeof(*arr));//1
    printf("%d\n", sizeof(arr[1]));//1
    printf("%d\n", sizeof(&arr));//4/8
    printf("%d\n", sizeof(&arr+1));//4/8
    printf("%d\n", sizeof(&arr[0]+1));//4/8

题目三

 char arr[] = {'a','b','c','d'};
 //strlen()函数接收的是字符串的地址,只认地址,并计算 以传入地址为始,以\0的上一个地址为终,始终地址存放的字符长度
    printf("%d\n",strlen(arr));//随机值,因为stelen计算字符串长度是找到\0之前的,没找到\0就随机值
   printf("%d\n", strlen(arr+0));//随机值
   // printf("%d\n", strlen(*arr));//实际上传入了一个字符‘a’,a的ASCII码是97,相当于把97这个地址传入strlen,越界非法访问地址,会崩溃
   // printf("%d\n", strlen(arr[1]));//崩溃
    printf("%d\n", strlen(&arr));//随机值
    printf("%d\n", strlen(&arr+1));//随机值,但和上一行一定相差4
    printf("%d\n", strlen(&arr[0]+1));//随机值,比之前的少1
    return 0;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值