C语言——函数指针与指针函数

发布于:2024-05-20 ⋅ 阅读:(131) ⋅ 点赞:(0)

一、函数指针

        1、定义

        顾名思义,函数指针就是函数的指针。它是一个指针,属于一个数据类型,其指向一个函数。如定义一个函数,其入口地址就是这个函数的指针,是个常量,可以用该常量给函数指针类型的变量赋值,如下:

void (*p_fun)();//定义函数指针变量
void fun()
{
//空函数;
}

p_fun = fun;//给变量赋值
p_fun = &fun;//这样的写法也认可
使用函数指针就在于便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开。

        2、使用例子

        如下,函数指针的简单使用,

#include <stdio.h>
int sum(int a,int b)
{
    return a+b;
}
int main()
{
    int sum1,sum2;
    int (*fun)(int x,int y);
    fun = sum;
    sum1 = (*fun)(1,2);
    sum2 = sum(1,2);
    printf("%d,%d",sum1,sum2);
    return 0;
}

其执行的结果为:

2,2

可以看出其结果一致,在使用函数指针时,通过用(*fun)取出存在这个地址上的函数,然后调用它。

        上面的例子比较简单,再看看下面的使用:

void Fun()
{
    printf("hello world!\n");
}

int main()
{
    void (*p)();
    *(int*)&p=(int)Fun;
    (*p) ();
    return 0;
}

首先,void (*p)();这句代码定义了一个指针变量p,其指向一个函数,这个函数的参数和返回值都是void。&p是求指针变量的地址(即地址的地址),(int *)&p表示将地址强制转换成指向int类型数据的指针,*(int*)&p=(int)Fun则表示,将函数的入口地址赋值给指针变量p。之后便于上面例子相同了。

        下面,再来看一个比较复杂的,其在单片机的固件中使用较多,

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

这是《C Traps and Pitfalls》这本经典的书中的一个例子。下面来逐步分析,第一步:void(*) (),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。第二步:(void(*) ())0,这是将 0 强制转换为函数指针类型,0 是一个地址,也就是说一个函数存在首地址为 0 的一段区域内。第三步:(*(void(*) ())0),这是取 0 地址开始的一段内存里面的内容,其内容就是保存在首地址为 0 的一段区域内的函数。第四步:(*(void(*) ())0)(),这是函数调用。好像还是很简单是吧,上面的例子再改写改写:(*(char**(*) (char **,char **))0) ( char **,char **);看不懂了就是参考这里

        3、函数指针数组

        欲将多个函数指针在内存中连续的放在一起,就可以定义为一个函数指针数组。如下:

char * (*p_fun[3])(char * p);
它是一个数组,数组名为 p_fun ,数组内存储了 3 个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。但这是一个指针数组,是数组类型。
一般使用方法如下:
void fun1(void)
{
    printf("1\n");
}
void fun2(void)
{
    printf("2\n");
}
void fun3(void)
{
    printf("3\n");
}
int main()
{
    void (*pf[3])();
    pf[0] = fun1; // 可以直接用函数名
    pf[1] = &fun2; // 可以用函数名加上取地址符
    pf[2] = &fun3;

    pf[0]();
    pf[1]();
    pf[2]();
    return 0;
}

二、指针函数

        指针函数, 即返回值为指针的函数, 实质上是一个函数。如:

int * fun(void);
char * fun(int a);
void * fun(char * a,char * b);

所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。

例如,求最大值函数(指针作为函数的返回值)

#include <stdio.h>
int *max(int *p1, int *p2) 
{
     if(*p1 > *p2)
         return p1;
     else return p2;
}
int main()
{
     int *p, a, b;
     a = 1; b = 2;
     p = max(&a, &b);
     printf("%d\n", *p);
     return 0;
}