函数指针数组:void ** cast

时间:2017-09-15 09:36:56

标签: c arrays void

我对c和c ++很新。我有一个任务(更多的是练习)将给定的c模块更改为c ++。为此,我必须先了解c文件。

我有两个具体问题,但我想简要介绍一下这部分功能。我尝试使用通用标识符。

c代码摘录:

有一个Broker提供注册回调的函数。 Broker在各自的数组中保存不同类型的回调。

首先,他们声明了几个函数指针来指定回调:

typedef bool (*ReadRequestCallback_tpf)  (param1 a, param2 b, param3 c);
typedef bool (*ReadResponseCallback_tpf) (param4 a, param5 b);
typedef bool (*WriteRequestCallback_tpf) (param6 a, param7 b, param8 c);
...

然后,他们为每种类型制作数组以保存注册的回调:

ReadRequestCallback_tpf  ReadRequest_apf  [MaxReadRequest];
ReadResponseCallback_tpf ReadResponse_apf [MaxReadResponse];
WriteRequestCallback_tpf WriteRequest_apf [MaxWriteRequest];

有注册新回调的功能:

void RegisterReadRequestCallback_v (ReadRequestCallback_tpf callback_pf){
    AddCallback_v((void**)ReadRequest_apf, (void*) callback_pf);
}
void RegisterReadResponseCallback_v (ReadResponseCallback_tpf callback_pf){
    AddCallback_v((void**)ReadResponse_apf, (void*) callback_pf);
}
void RegisterWriteRequestCallback_v (WriteRequestCallback_tpf callback_pf){
    AddCallback_v((void**)WriteRequest_apf, (void*) callback_pf);
}

AddCallback_v的签名就像:

void AddCallback_v (void* Array_apv[], void* function_pf)

我的问题:

  1. (void**) array_apf真的是void* array_apv吗? 因此,'void-pointer指向void-pointer'的'函数指针数组'的转换等于'void指针指向void-pointer数组'? 既然它有效,它似乎就是这样。但我真的不明白。

  2. 当尝试将其(或部分)更改为c ++时,使用模板而不是强制转换为(void *)是一种更好的方法吗?

  3. 这是我第一次来这里。我希望,我可以解释我的问题。如果需要澄清某些事情,请告诉我。

    亲切的问候并提前感谢

2 个答案:

答案 0 :(得分:1)

  1. 当一个数组传递给一个函数时,它会自动转换为指向第一个元素的指针。因此,在函数声明中,TYPE array[]等同于TYPE *array。因此,void *array[]相当于void **array

  2. 模板的一个目的是避免对通用函数使用void *类型,因为编译器无法确保在将其转换回原始类型时使用指针。所以,模板通常是比采用void*参数的函数更好的解决方案。

答案 1 :(得分:1)

C代码实际上已被破坏。虽然任何指向任何对象的指针都可以转换指向void 的指针,但对于指向函数的指针,这不是真的。此外,无法保证指向函数的指针可以重新解释作为C中的指向void的指针。这意味着函数

void RegisterReadRequestCallback_v (ReadRequestCallback_tpf callback_pf){
    AddCallback_v((void**)ReadRequest_apf, (void*) callback_pf);
}

在许多方面被打破,包括它打破严格的别名。这是错误的,它会伤害。

这样做的意图显然是有一个名为AddCallback_v的泛型函数,它获取了一个指向回调数组的指针,以及一个新的回调函数,但是C并不能保证它会像那样工作!

在C中,对此进行编码的正确方法是让Readrequest_apf等为通用指针到函数的数组;在调用它们之前,它会被转回ReadRequestCallback_tpf等,即

typedef bool (*GenericCallback_tpf)();

GenericCallback_tpf ReadRequest_apf[MaxReadRequest];

void AddCallback_v(GenericCallback_tpf callback_array[]);

void RegisterReadRequestCallback_v (ReadRequestCallback_tpf callback_pf){
    AddCallback_v(ReadRequest_apf, (GenericCallback_tpf)callback_pf);
}

致电:

((ReadRequestCallback_tpf)ReadRequest_apf[i])(param1, param2, param3);

在C ++中,您为这些*_apf中的每一个使用仿函数向量;因此不需要演员阵容。