指针函数 AND 函数指针 AND 函数指针数组 AND 指向函数指针数组的指针

指针函数

  • 形如“指针数组”,“指针函数”是一个“函数”,函数的返回类型是指针。
定义
    类型标识符 *函数名(参数表)
char *reverse(char *left, char *right);

reverse是一个函数,它的返回类型是一个字符型的指针,函数的返回值必须在主调用函数中用一个相同类型的的指针变量来接收。

char *my_strcpy(char *dst, const char *src)
{
    char *ret = dst;
    assert(dst);
    assert(src);

    while (*dst++ = *src++)
    {
        ;
    }
    return ret;
}

int main()
{
    char arr1[] = "abcdef";
    char arr2[20] = { 0 };
    char *ret = my_strcpy(arr2, arr1);
    printf("%s\n", ret);

    system("pause");
    return 0;
}

这个例子使用的是strcpy的模拟实现,此处my_strcpy就是一个指针函数,本质是一个函数,返回值是一个字符型指针,在主函数中使用同类型的字符型指针接收。


函数指针

  • 形如“数组指针”,“函数指针”是一个“指针”,指向了函数的入口;
先看一段代码:
#include <stdio.h>
#include <stdlib.h>

void test(void)
{
    printf("i love you\n\n")int main()
{
test();
printf("test = %p\n", test);
printf("&test = %p\n", &test);

system("pause");
return 0;
}

(函数名)和(&函数名)都输出了函数的地址

函数的地址如何存放呢?
我们不禁想到了“数组”的地址是通过“数组指针”来存放的,那函数的地址是否可以通过“函数指针”来存放呢?还是可以通过“指针函数”来存放?

void (*ptest1)();
void *ptest2();

首先,能存储地址的必须是一个指针变量,分析可知,ptest1先和*结合,形成指针,指向一个函数,指向的函数无参数,返回值类型为void。

定义
    类型标识符 (*指针变量名)(参数表)

举例:大家来说说一下几个式子分别代表什么含义?

1.char* fun1(char* p1, char* p2);
2.char* *fun2(char* p1, char* p2);
3.char* (*fun3)(char* p1, char* p2);

1. 是指针函数,fun1是函数名,p1、p2是参数,其类型都为char *,函数的返回值类型是char*,是一个一级指针
2.是指针函数,同1,只不过函数的返回类型为char **,是一个二级指针。 fun2是函数名,p1、p2是参数,其类型都为char *,函数返回值类型是char **,是一个二级指针
3.是函数指针,fun3是指针变量名,指向了一个函数,这个函数有两个参数为p1、p2,其类型都是char *,函数的返回值类型是char *,如果看不懂可以把式子改写为:char* (*)(char* p1,char* p2) fun3

看了这些后,我们看两个代码吧!简述一下它们代表了什么含义?

1.(*(void(*)())0)();
答:分析步骤如下:
-首先这个式子看一下没有变量只有常量0,所以我们的突破口就是这里。
① void(*)() 是一个函数指针,没有参数没有返回值。
② (void(*)())0 是将0强转为函数指针类型,0存放的是一个地址,所以,一个函数存在首地址为0的一段区域内。
③ (*(void(*)())0) 取0地址开始处的一段内村里面存放的内容,内容就是保存在首地址为0处的一段区域内的函数。
④ (*(void(*)())0)() 是函数调用,调用了0地指出的函数,此函数没有参数。

总结:(*Func)()为调用Func指向函数的方式
看了上述总结,是不是有一点懂了?那再看一个同类型的吧!

(*(char** (*)(char**, char**))0)(char**, char**);
答:这里很容易的就知道啦,此时表达的是,调用0地址处的函数,此函数
有2个参数,类型都为char**,有返回值,是char**类型的。
2.void (*signal(int, void(*)(int)))(int);
答:从难到简的方式我们先看:
① void(*)(int) 我们会知道这个式子的应该是void(*handle(int),无返回值。
② void (*signal(int, void(*)(int)))(int) 可以写为void(*)() signal(int, void(*)(int)),void(*)(int)是返回类型signal(int, void(*)(int))是一个函数,所以,此式子表达的是一个返回指向返回void值的函数的指针的函数。
③void (*signal(int, void(*)(int)))(int) 是一个函数的声明,是一个返回指向返回void值的函数的指针的函数的声明。
可以简化为:
typedef void(*pfun_t)(int);
pfun_t signal(int pfun_t);

函数指针数组

大家都知道“数组”是存放相同类型数据的存储空间,“函数指针”是一个指向函数的“指针”,那我们就可以知道,“函数指针数组”是一个存放指向函数的指针的数组,也可以说为是一个存放函数地址的数组。

定义

例如:int (*parr1[10])()
首先parr1先和[]结合,说明parr1是一个数组,那么数组的内容就是int (*)()类型的函数指针
简述一下下列的代码分别表示什么意思?

1.char* (*pf1[3])(char* p);
2.int *pf2[3]();
3.int (*)() pf3[3]

1.这是定义一个函数指针数组。它是一个数组,数组名为 pf1,数组内存储了 3 个指向函数的指针。
2.这种写法属于错误写法,它什么都不能表示。
3.这个是定义了一个函数指针数组。它是一个数组,数组里面有3个元素,每个元素的类型是int(*)()类型的,所以,这个也是一个函数指针数组,可以写为int(*pf3[3])()。

函数指针数组的应用

我们通过函数指针数组存放每个算法函数的地址,不就可以找到每个元素函数了吗?
这里写图片描述

void menu(void)
{
    printf("**************************\n");
    printf("**   1.add      2.sub   **\n");
    printf("**   3.mul      4.div   **\n");
    printf("**   0.exit             **\n");
    printf("**************************\n");
}

int add(int x, int y)   //加法
{
    return x + y;
}
int sub(int x, int y)   //减法
{
    return x - y;
}
int mul(int x, int y)   //乘法
{
    return x * y;
}
int dive(int x, int y)  //除法
{
    return x / y;
}
void test(void)
{
    int input = 0;
    int x = 0, y = 0;
    int ret = 0;
    int(*p[5])(int x, int y) = { 0, add, sub, mul, dive };  //函数指针数组,存放了各个函数的地址
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        if ((input > 0 && input < 5))
        {
            printf("请输入操作数(x y):>");
            scanf("%d%d", &x, &y);
            ret = (*p[input])(x, y);
            printf("ret = %d\n", ret);
        }
        else if (input == 0)
        {
            return;
        }
        else
        {
            printf("输入有误\n");
        }
    } while (input);
}
int main()
{
    test();
    system("pause");
    return 0;
}

这里写图片描述


指向函数指针数组的指针

首先指向函数指针数组的指针应该是一个指针,那么,指针指向一个数组,数组元素都是函数指针;

void (*(*pp)[10])(const int *);

它表示的是一个指向函数指针数组的指针,这个指针指向的数组有10个元素,每个元素都是函数指针,指向的函数无返回值,有一个参数,是不可修改的整型指针。


小总结

1.函数指针是指针,它存放的是函数的地址
2.函数指针数组是数组,它的元素类型都是函数指针
3.指向函数指针数组的指针是指针,它存放的是函数指针数组的地址

猜你喜欢

转载自blog.csdn.net/meng_lemon/article/details/80631889