将函数作为 void * 传递,其参数也作为 void *

passing a function as void * with its arguments as void * as well

我很难将函数作为 void* 传递给它的参数 void*:

#include <stdlib.h>

void* hello(void* (*calc)(void *), void* op){
    int val = *(int *) op;
    int* retval = malloc(sizeof(int));
    *retval = calc(val);
    return retval;
}


int calc(int b){
    int a = 5;
    int sum = a+b;
    return sum;
}

int main(){
    int arg = 4;
    int value = *(int*) hello(&calc,&arg);
    return 0;
}

错误是:

40392282.c: In function ‘hello’:
40392282.c:6:20: warning: passing argument 1 of ‘calc’ makes pointer from integer without a cast [-Wint-conversion]
     *retval = calc(val);
                    ^~~
40392282.c:6:20: note: expected ‘void *’ but argument is of type ‘int’
40392282.c:6:13: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
     *retval = calc(val);
             ^
40392282.c: In function ‘main’:
40392282.c:19:31: warning: passing argument 1 of ‘hello’ from incompatible pointer type [-Wincompatible-pointer-types]
     int value = *(int*) hello(&calc,&arg);
                               ^
40392282.c:3:7: note: expected ‘void * (*)(void *)’ but argument is of type ‘int (*)(int)’
 void* hello(void* (*calc)(void *), void* op){
       ^~~~~
40392282.c:19:9: warning: unused variable ‘value’ [-Wunused-variable]
     int value = *(int*) hello(&calc,&arg);
         ^~~~~

关于如何实际将函数作为类型为 void* 的参数传递的任何建议?

谢谢@2501,但我收到以下错误。

hello.c: In function ‘hello’:
hello.c:12:18: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
 int(*calc)(int) =calc_call;
                  ^
hello.c: In function ‘main’:
hello.c:34:35: warning: passing argument 1 of ‘hello’ from incompatible pointer type [-Wincompatible-pointer-types]
   int value = *(int *) hello(&calc,&arg);
                                   ^
hello.c:10:7: note: expected ‘void * (*)(void *)’ but argument is of type ‘int (*)(int)’
 void* hello(void* (*calc_call)(void *), void* op){       

当我编写代码时:

 void* hello(void* (*calc_call)(void *), void* op){
        int* const integer = op;
        int(*calc)(int) =calc_call;
        *integer=calc(*integer);
        return op;
    }


    int calc(int b){
        int a = 5;
        int sum = a+b;
        return sum;
    }

    int main(){
        int arg = 4;
        int value = *(int*) hello(&calc,&arg);
        return 0;
    }

首先我想说你的做法非常非常糟糕。您正在将一个接受 returns 整数的函数转换为接受 returns 一个 void* 的函数,然后在您的函数 (hello) 中保存 returned 值作为一个 int*,并继续 return 将 int* 转换为 void*,最后将其转换回 int(不释放内存,我可能会补充)。

您需要知道的第一件事是您可以将任何内容强制转换为空指针。这是人们偏离它们的原因之一。就个人而言,我喜欢玩 hacky 代码并尝试解决问题,也许这就是您正在做的事情。但是请不要在任何项目或您的工作中包含此类代码,尤其是在您进行协作时。

现在,回到空指针。 ANYTHING 可以是空指针。我怎么强调都不过分。例如,

int *****arr; // 5D array
void* arr_ptr = (void*)arr;

是完全有效(虽然不是很好)的代码。您还可以将非指针类型转换为 void 指针。

调用函数: int *value = (int*) hello( (void* (*)(void*))calc, (void*)arg ); 您需要将函数和参数转换为正确的指针类型。请注意,我没有使用 &calc&arg,因为我们不需要。请记住,我们可以将任何内容强制转换为 void*,那么如果不需要的话,为什么还要费心处理引用和取消引用呢? calc 的转换可以简化为 (void*)calc,我只是使用上面的完整转换来说明发生了什么。

你好函数

void* hello(void* (*func)(void *), void* op)
{
    int* retval = malloc(sizeof(*retval));
    *retval = (int)func(op);
    return retval;
}

我在这里只更改了函数的名称(您不想将函数指针命名为与实际函数同名,这可能会产生意想不到的结果)。

如果您希望代码可移植到不同的类型,我建议稍微修改一下:

void* hello(void* (*func)(void *), void* op, int size)
{
    void** retval = malloc(size);
    *retval = func(op);
    return retval;
}

并像这样从 main 中调用它:

 int *value = (int*) hello((void*)calc, (void*)arg, sizeof(int));

附加参数指定该函数将 return sizeof(int) 字节,因此您知道您正在获取正确数量的数据。

最后,在您的 main 中,您不应该立即取消引用指针,而是取值并释放内存,以避免内存泄漏。

您的代码有几个错误,但一个很关键:将函数指针转换为不兼容的类型并调用它。当您调用参数 calc 时,这发生在函数 hello 中,该参数的类型 void*(*)(void*) 从不兼容的类型 int(*)(int).
转换而来 此调用将导致未定义的行为。

传递函数指针的正确解决方案是使用正确的类型,
在这种情况下:int(*)(int).

不需要分配内存,因为调用函数指针的return值可以存储在同一个变量中:

void* hello( int( *calc)( int ) , void* op )
{
    int* const integer = op ;
    *integer = calc( *integer );

    return op;
}

如果您坚持在函数 hello 中的第一个参数使用 void*(*)(void*) 类型,那么您必须将参数转换回正确的类型:

void* hello( void*( *calc )( void* ) , void* op )
{
    int* const integer = op ;
    int ( *correct )( int ) = ( ( int )( * )( int ) )calc;
    *integer = correct( *integer );

    return op ;
}