TaterLi's LazyBlog

自言自语,不喜绕路,科学上网,远离天国.

@TaterLi3月前

11/19
15:42
技术控

一点也不神秘的函数的指针

大家都知道指针就是东西的地址.变量有指针,函数也有.而且很巧妙.

看一个简单例子.

#include <stdio.h>

int testfunc(int a)
{
    printf("My a = %d", a);
}

int main()
{
    int (*myfunc)(int) = testfunc;
    myfunc(5);
    return 0;
}
~

结果就是执行了testfunc,并且传入了5.好像这挺无聊的,看不出什么优势.如果是多个一组函数呢.

#include <stdio.h>

int test1(int a)
{
    printf("My a = %d\n", a);
}

int test2(int b)
{
    printf("My b = %d\n", b);
}

int main()
{
    int (*myfunc[2])(int) = {test1, test2};
    (myfunc[0])(5);
    (myfunc[1])(5);
    return 0;
}

我相信你已经看得出声明格式了.

#include <stdio.h>

int test1(int a, int b)
{
    printf("My a = %d\n", a + b);
}

int test2(int c, int d)
{
    printf("My b = %d\n", c * d);
}

int main()
{
    int (*myfunc[2])(int, int) = {test1, test2};
    (myfunc[0])(5, 4);
    (myfunc[1])(5, 4);
    return 0;
}

来个复杂的,这个应该知道结果了吧.

My a = 9
My b = 20

好的,那么继续.不知道具体类型怎么办.那就void.void兼容性是一流的.但是,void一定要指针方式传入,否则是incomplete type,另外void是万能类型,需要转化.

#include <stdio.h>

int test1(void *a, void *b)
{
    printf("My a = %d\n", *(int *)a + * (int *)b);
}

int test2(void *c, void *d)
{
    printf("My b = %d\n", *(int *)c * *(int *)d);
}

int main()
{
    int val1 = 5;
    int val2 = 10;

    int (*myfunc[2])(void *, void *) = {test1, test2};
    (myfunc[0])(&val1, &val2);
    (myfunc[1])(&val1, &val2);
    return 0;
}

我们用int *转换了void类型,使得变量成为int *,然后用*取出真内容,因为我们用&传进去了一个地址.所以要*取出.

如果要加修饰符,怎么办呢.直接加就是了.

#include <stdio.h>

int test1(const void *a, const void *b)
{
    printf("My a = %d\n", *(int *)a + * (int *)b);
}

int test2(const void *c, const void *d)
{
    printf("My b = %d\n", *(int *)c * *(int *)d);
}

int main()
{
    int val1 = 5;
    int val2 = 10;

    int (*myfunc[2])(const void *, const void *) = {test1, test2};
    (myfunc[0])(&val1, &val2);
    (myfunc[1])(&val1, &val2);
    return 0;
}

既然void是万能的,那么字符串呢?先复习下基本main函数的样子.

#include <stdio.h>

int main(int argc,char *argv[]){

}

其中argv是字符串的数组,而数组又是指针,也就是char b[] ≈ char *b(区别只差在是否申请了空间,都是字符串),那么实际上可以写char **argv,就是字符串数组的指针了.(当然,很拗口的读法是字符串指针[数组越≈指针]的指针).如果一个不小心,就会发生Segmentation fault.我到群里随便问了下,有人答案是这样的.

int test1(const void *a, const void *b)
{
    if(strcmp((*(char **)a, *(char **)b))
{
    printf("a bigger than b\n");
    }
    else
    {
        printf("b bigger than a\n");
    }
}

想得太复杂不说,实际上很简单啊.

int test1(const void *a, const void *b)
{
    if(strcmp((char *)a, (char *)b))
    {
        printf("a bigger than b\n");
    }
    else
    {
        printf("b bigger than a\n");
    }
}

因为strcmp已经是传入const char *了,所以…

但是,我们现在依然一个一个调用,好像没有体验出优势啊.实际上,函数也可以作为参数,传递进别的函数里面.

 

一点也不神秘的函数的指针

  1. 叶子
    Google Chrome 62Google Chrome 62WindowsWindows

    函数指针我习惯上用来做动态的驱动加载。我觉得这样,我就可以同时准备多个驱动,然后动态切换了。从整个程序上看,就变成修改硬件的时候,我只需要更改下驱动函数的指针的值。

    回复