You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过void指针访问传入函数的函数指针数组元素?

如何通过void*传递函数指针数组并访问其元素?

问题背景

因使用LVGL图形库,必须通过lv_obj_add_event_cb(obj, callback_fn, my_event_trigger, user_data)以void*类型传递函数指针数组作为user_data。触发事件时在回调函数中通过lv_event_get_user_data(e)获取该数组,但无法直接访问数组元素并调用对应函数。

现有可正常运行的示例

示例1:通过void*传递普通数组

#include <stdio.h>

void function(void* ptr)
{
    int* arr = ptr;

    for(int i = 0; i < 5; ++i)
    {
        printf("%d ", arr[i]);
    }
}

int main()
{
    int arr_nums[5] = { 1, 2, 3, 4, 5 };

    function((void*)arr_nums);

    return 0;
}

输出:

1 2 3 4 5 

示例2:通过void*传递单个函数指针

#include <stdio.h>

int add(int a, int b)
{
    return (a + b);
}

int sub(int a, int b)
{
    return (a - b);
}

int mult(int a, int b)
{
    return (a * b);
}

int divide(int a, int b)
{
    return (a / b);
}

int function(void *ptr)
{
    return ((int(*)(int, int))ptr)(4, 2);
}

int main()
{
    printf("%d\n", function((void*)add));
    printf("%d\n", function((void*)sub));
    printf("%d\n", function((void*)mult));
    printf("%d\n", function((void*)divide));

    return 0;
}

输出:

6
2
8
2

示例3:通过void*传递函数指针数组的单个元素

// 复用示例2中的add/sub/mult/divide函数和function函数
int main()
{
    int (* fp_arr[4])(int, int) = { add, sub, mult, divide };
    
    printf("%d\n", function((void*)fp_arr[0]));
    printf("%d\n", function((void*)fp_arr[1]));
    printf("%d\n", function((void*)fp_arr[2]));
    printf("%d\n", function((void*)fp_arr[3]));
    
    return 0;
}

输出:

6
2
8
2

问题场景:传递整个函数指针数组并访问元素

需要修改function函数,实现通过传入的void*访问函数指针数组的指定元素(比如调用下标为2的mult函数):

// 复用add/sub/mult/divide函数
int function(void *ptr)
{
    // 如何实现类似ptr[2]调用mult的操作?
    return ((int(*)(int, int))ptr)(4, 2); 
}

int main()
{
    int (* fp_arr[4])(int, int) = { add, sub, mult, divide };
    
    printf("%d\n", function((void*)fp_arr));
    
    return 0;
}

解决方案

核心是将void*转换为指向函数指针的指针或指向函数指针数组的指针,之后即可像普通数组一样通过下标访问元素。

方法1:转换为指向函数指针的指针

数组名传递时会退化为指向第一个元素的指针,所以我们可以把void*转换为int(**)(int, int)(即指向函数指针的指针),之后直接用下标访问:

int function(void *ptr)
{
    // 将void*转换为指向函数指针的指针
    int (**fp_ptr)(int, int) = (int (**)(int, int))ptr;
    // 访问数组第2个元素(下标从0开始)并调用
    return fp_ptr[2](4, 2);
}

方法2:转换为指向函数指针数组的指针

也可以直接转换为指向整个函数指针数组的指针,解引用后得到数组再访问元素:

int function(void *ptr)
{
    // 将void*转换为指向函数指针数组的指针
    int (*(*fp_arr)[4])(int, int) = (int (*(*)[4])(int, int))ptr;
    // 解引用得到数组,再访问第2个元素并调用
    return (*(*fp_arr)[2])(4, 2);
}

两种方法都能实现需求,方法1更简洁,适合大多数场景。


内容的提问来源于stack exchange,提问作者cmoran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:48:27