首页 > 解决方案 > C:将通用输入 arg (void*) 中的函数指针类型转换为特定的 (char*/int *) arg 和/或不同的返回类型、void、int

问题描述

我有特定的数据类型:

typedef struct _A_s { ... } A_t;
typedef struct _B_s { ... } B_t;

我也有特定的功能来操作这些(例如A_t * init_A(); free_A(A_t *); print(A_t *);等)。

第三个函数通过 avoid *和函数指针接收任何这些数据结构类型,以便释放和打印其输入。我想保持这个函数通用,因此转换A_t*void*. 但我不确定这将如何与函数指针一起使用。

这是一个粗略的(对不起!)草图:

typedef (void )(*free_generic_t)(void *);
typedef (void )(*print_generic_t)(void *);
void myfunc(
  void *object,
  free_generic_t free_fn,
  print_generic_t print_fn
){
  ...
  print_fn(object);
  free_fn(object);
}

我的目标是这样做:

A_t *a = init_A(...);
B_t *b = init_B(...);
myfunc((void *)a, free_A, print_A);
myfunc((void *)b, free_B, print_B);

gcc抱怨因为-Werror=incompatible-pointer-types,我想继续。忽略此警告,程序可以正常工作。

当我做这个类型转换时我有一个 SIGSEGV它工作正常并通过了valgrind测试:

myfunc(
  (void *)a,
  (free_generic_t )free_A,
  (free_generic_t )print_A
);

问题 1:在上述场景中,将函数类型转换为函数指针,我能走多远?假设输入参数的数量是固定的。也就是说, allprint_A()只接受 1 个参数,这将是一个指针。

问题 2:当其中一些特定功能return int和一些什么都没有时,问题变得更加复杂(void)。我可以调整通用函数指针以return int适应特定函数的两种风格,即使其中一些返回void

更新:当我对函数指针进行类型转换时,我没有得到 SIGSEGV,这是我的错误。我已经编辑了我的帖子。

标签: cfunctionpointerscastinggcc-warning

解决方案


给那些结构

typedef struct _A_s { ... } A_t;
typedef struct _B_s { ... } B_t;

指向释放器函数的指针并将其 A_t * init_A();分别填充到B_t * init_B();.

然后你可以为它们编写一个通用的释放器,通过存储的指针间接调用释放器。

// Anything, which is shared between structures
typedef struct _X_s { void (*deallocator)(void *); ... } X_t;

typedef struct _A_s { X_t x; ... } A_t;
typedef struct _B_s { X_t x; ... } B_t;

然后

void deallocate(X_t *x){
    x -> deallocator(x);
}

int main(void){
    A_t *a = init_A();
    B_t *b = init_B();

    deallocate((X_t *)a);
    deallocate((X_t *)b);
}

请注意,这只是您如何做到这一点的概念。您必须自己制定详细信息并添加有效性检查等。


推荐阅读