函数指针与函数指针数组

1. 函数指针

函数指针:指向函数的指针,存放函数地址的指针。

&func_name 取到的就是函数的地址;

直接用 func_name 也可以得到函数的地址;

数组名  &数组名  两者不等价 
函数名  &函数名  两者等价

如何定义一个函数指针变量呢?

int (*pf)(int, int) = &Add;

这里的Add是一个函数名,函数接收两个int型的参数,函数的返回类型也是int.

因此函数指针变量定义应该是:

函数返回类型 (*指针名称) ( 函数传参类型1 , 函数传参类型2 , ...)= &函数名

定义和使用的例子:

int Add(int x, int y)
{
    return x + y;
}

int main()
{
    int  (*fp2) (int, int) = &Add;
    int ret = (*fp2)(5, 4);
    //也可以这么来调用:int ret = fp2(5, 4); 
    printf("5 + 4 =%d\n", ret);
}

(*fp2)(5, 4) 和 fp2(5, 4) 都可以调用函数,这说明那颗星是一个摆设!

题目1:如何对下面的代码进行解析?

(*(void(*)())0) ();

void(*p)() 可以看做是对函数指针p进行声明的语法,这里p的类型就是 void(*)() ,所以 (void(*)())0 就是对 0 进行强制类型转换,把他转换成一个函数指针!(*(void(*)())0) 是对函数指针进行解引用,因此这段代码的作用就是调用0地址处的函数:该函数无参数,返回类型是 void。

题目2: 如何对下面的代码进行解析?

void (* signal(int, void(*)(int))) (int);
  • 首先从 signal 入手,他首先和 () 进行结合,说明他是一个函数;
  • signal 函数有两个参数,参数1是 int 型的,参数2是 void(*)(int) 型的,也就是函数指针型的;
  • 函数名,函数参数都确定了,拿掉这部分,剩下的就是函数返回值类型,剩下了什么呢?是: void (*) (int) ,可见 signal 函数的返回类型是一个函数指针。

因此上述语句其实就是对 signal 函数进行声明的语句。

自己实现了一个这样的 signal 函数:

void (* signal(int, void(*)(int))) (int);

void wash(int n)
{
    printf("I will wash %d kg vegetables today.\n", n);
    printf("after vegetables are washed, please start cooking!\n");
}

void cooking(int n)
{
    printf("I will cooking %d kg vegetables.\n", n);
}

void (* signal(int n, void(*p)(int))) (int)
{
    p(n);
    return cooking;
}

int main()
{
    int n = 5;
    void (*w) (int n);
    w = signal(n, wash);
    w(n);
    return 0;
}

注意,上述 signal 函数的声明如果这样写是不被允许的:

void (*)(int) signal(int, void(*)(int));  // 不被允许的写法,虽然更容易读懂

但是有没有更好的写法呢?当然是有的:

typedef void(*pfun_t)(int);  // 对void(*)(int)的函数指针类型重命名为 pfun_t
pfun_t signal(int, pfun_t);

这样,上述代码就可以简化成:

typedef void(*pfun_t)(int);  // 对void(*)(int)的函数指针类型重命名为 pfun_t

pfun_t signal(int number, pfun_t call_pfun);

void wash(int n)
{
    printf("I will wash %d kg vegetables today.\n", n);
    printf("after vegetables are washed, please start cooking!\n");
}

void cooking(int n)
{
    printf("I will cooking %d kg vegetables.\n", n);
}

pfun_t signal(int n, pfun_t p)
{
    p(n);
    return cooking;
}

int main()
{
    int n = 5;
    void (*w) (int n);
    w = signal(n, wash);
    w(n);
    return 0;
}

2. 函数指针数组

函数指针数组里面可以存放同类型的函数指针

int Add(int x, int y)
{
    return x + y;
}

int Sub(int x, int y)
{
    return x - y;
}

int main()
{
    int (* pf_arr[2]) (int, int) = {Add, Sub};
    int ret = pf_arr[1](5, 3);
    printf("%d\n", ret);
    return 0;
}

这里 pf_arr 的声明也可以这样:

typedef int (add_or_sub) (int x, int y);
add_or_sub *pf_arr[2] = {Add, Sub};

还可以这样:

typedef int (* add_or_sub) (int x, int y);
add_or_sub pf_arr[2] = {Add, Sub};

3. 指向函数指针数组的指针

指向函数指针数组的指针是一个 指针 ,指针指向一个 数组 ,数组的元素都是 函数指针 .

int (* arr[2]) (int, int) = {Add, Sub};  // p2 是一个函数指针数组
int (* (*parr)[2]) (int, int) = &arr; // p3就是一个指向【函数指针数组】的指针

总结, 如果一个指针parr指向了一个数组arr,那么这个指针可以以这种方式进行声明:在等号左边,把声明arr的代码拷贝过来,用(*parr)来对该声明中的arr进行字符串替换;等号右边替换成&arr。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值