【问题标题】:Using a function from a function array stored in a struct in C使用存储在 C 结构中的函数数组中的函数
【发布时间】:2021-03-28 04:24:42
【问题描述】:

我声明了一个这样的结构:

typedef struct s_data {

    char buff[2048];
    int len; 
    void *func[10];
    struct data *next;

}               t_data;

在我的代码中,当传递 *data 时,我分配了一些函数(只给出一个,这样更容易理解)

void init_data(t_data *data)
{
    data->len = 0;
    data->func[0] = &myfirstfunctions;
    //doing the same for 9 others

}

我的第一个函数是作为参数 *data 和一个 int。 然后,我尝试在另一个函数中使用这个函数,做

data->func[0](data, var);

我尝试了这个和其他一些涉及尝试寻址 (*func[0]) 的语法,但它们都不起作用。我从那里的其他更复杂的问题中了解到我不应该像这样存储我的函数,或者应该将它转换为另一个 typedef,但我并没有真正理解所有内容,因为我是编程新手。

【问题讨论】:

  • void * 是一个无类型指针。编译器不知道指针真正指向什么,这意味着如果不强制转换为正确的类型,就无法取消引用它。更好的解决方案是使func 成为一个正确类型的数组。函数类型的类型别名(使用 typedef 创建)会有所帮助。
  • 感谢@Someprogrammerdude!根据您的回答,我只是尝试将我的 func 数组更改为 int 数组,因为我的所有函数都将返回一个 int。但是当我尝试分配它时:data->func[0] = &myfirstfunction;,我收到了错误分配的警告('int ' from 'int ()(t_data *, int)') .我想我从警告中了解到问题来自我的论点,但我错过了什么?谢谢你的时间,

标签: arrays c structure function-pointers


【解决方案1】:

void* 只能可靠地用作通用 object 指针(“指向变量的指针”)。不作为通用函数指针。

但是,只要您只调用具有正确类型的实际函数,您就可以安全地在不同的函数指针类型之间进行转换。因此,可以只使用任何函数指针类型作为通用类型,如下所示:

void (*func[10])(void);
...
func[0] =  ((void)(*)(void))&myfirstfunction;
...
((whatever)func[0]) (arguments); // call the function

您可能会注意到,C 中的函数指针语法很糟糕。所以我建议使用 typedefs:

typedef void genfunc_t (void);
typedef int  somefunc_t (whatever*); // assuming this is the type of myfirstfunction

然后代码变得更容易阅读和编写:

genfunc_t* func [10];
...
func[0] = (genfunc_t*)&myfirstfunction;
...
((somefunc_t*)func[0]) (arguments);

【讨论】:

    【解决方案2】:

    如果您的所有函数都具有相同的签名,您可以这样做:

    #include <stdio.h>
    
    typedef void (*func)(void *, int);
    
    struct s_data {
            char buff[2048];
            int len;
            func f[10];
            struct s_data *next;
    };
    
    static void
    my_first_function(void *d, int x)
    {
            (void)d;
            printf("%d\n", x + 2);
    }
    
    static void
    init_data(struct s_data *data)
    {
            data->len = 1;
            data->f[0] = my_first_function;
    }
    
    int
    main(void)
    {
            struct s_data d;
            init_data(&d);
            d.f[0](NULL, 5);
            return 0;
    }
    

    如果你的函数有不同的签名,你会想要使用联合,或者你可能需要结构的几个不同成员来存储函数指针。

    【讨论】:

    • 你为什么需要做 (void)d ,先生?
    • @snr (void) 强制转换是为了禁止编译器警告未使用的参数。
    【解决方案3】:

    问题是你实际上并没有声明一个函数指针数组。您实际上所做的是指向 void 的指针数组。

    声明函数指针的语法如下:

    function_return_type (*pointer_name)(arg1_type,arg2_type,...);

    然后你可以创建一个指向函数的指针数组:

    function_return_type (*arr_name[])(arg1_type, arg2_type,...)

    因此,结构的声明应如下所示:

    typedef void (*pointer_to_function)(void *, int);
    
    struct s_data {
            char buff[2048];
            int len;
            pointer_to_function array_of_pointeters[10];
            struct s_data *next;
    };
    
    

    祝你好运:)

    【讨论】:

    • 谢谢,成功了!对于那些感兴趣的人,像上面一样,我声明 typedef void (*func)(void *, int);然后, func f[10];在我的结构中。在分配期间,我只需要将我的函数转换为 (func) 所以 data->f[0] = (func) &myfirstfunction;它奏效了。再次感谢!
    • 我们刚刚在课堂上通过了这个话题,所以你的例子对我们也很有帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多