【问题标题】:function pointer array: void** cast函数指针数组:void** cast
【发布时间】:2017-09-15 09:36:55
【问题描述】:

我对 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 to void-pointer”等于“void-pointer to an array of void-pointer”? 既然它有效,它似乎是这样。但我真的不明白。

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

这是我在这里的第一个条目。我希望,我可以解释我的问题。如果有什么需要澄清的,请告诉我。

提前致以诚挚的问候和感谢

【问题讨论】:

  • C 和 C++ 不是同一种语言,您实际使用的是哪一种?
  • 实际代码是用C写的。每段代码都是用C写的。以后应该用C++写。
  • 你可以尝试使用 std::function 的向量来代替数组

标签: c arrays void


【解决方案1】:

C 代码实际上已损坏。 任何指向任何对象的指针都可以转换指向void的指针,但对于指向函数的指针则不是这样时间>。此外,不能保证指向函数的指针可以在 C 中重新解释pointer-to-void。这意味着函数

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

在很多方面都被破坏了,包括它破坏了严格的别名。真是错得让人心疼。

这样做的目的显然是有一个名为 AddCallback_v 的通用函数,它获取指向回调数组的指针,以及一个新的回调函数,但是 C 不保证它会那样工作!

在 C 中,编写此代码的正确方法是让 Readrequest_apf 等成为通用 pointers-to-functions 的数组;在调用它们之前将被转换回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 使用 仿函数向量;因此不需要演员表。

【讨论】:

    【解决方案2】:
    1. 将数组传递给函数时,它会自动转换为指向第一个元素的指针。所以在函数声明中,TYPE array[] 等价于TYPE *array。因此,void *array[] 等价于void **array

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

    【讨论】:

      猜你喜欢
      • 2013-11-14
      • 2020-04-01
      • 2018-03-05
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      相关资源
      最近更新 更多