函数指针转换

时间:2017-02-01 08:05:24

标签: c pointers function-pointers

大家好,我目前正面临一个非常讨厌的问题:

我正在编写一个使用函数指针工作的回调管理器系统,现在我已经分配了一些其他非void函数指针的void函数指针,我已经意识到它不是实际上允许在C。

目前我正在考虑构建void指针,以便匹配我的每个回调的原型函数,但我无法理解如何实现强制转换

它是否可行或是否应采用其他解决方案?

目前这些是我的回调容器及其typedef:

typedef void modbus_read_t(unsigned int uid, unsigned int address, unsigned int count, char* response);
typedef void modbus_write_t(unsigned int uid, unsigned int address, unsigned int *data, char* response);

typedef void system_read_t(unsigned int uid, unsigned int var_number, unsigned int count, char* response);
typedef void system_write_t(unsigned int uid, unsigned int var_number, struttura_system *storage, char* response );

void (*M_callbacks_r[3]) (unsigned int uid, unsigned int address, unsigned int count, char* response);
void (*M_callbacks_w[2]) (unsigned int uid, unsigned int address, unsigned int *data, char* response);
void (*P_callbacks_r[2]) (unsigned int uid, unsigned int var_number, unsigned int count, char* response);
void (*P_callbacks_w[2]) (unsigned int uid, unsigned int var_number, struttura_system *storage, char* response );

这是注册回调函数的原型:

void registerCallback(int systemType,int operationType, void (callback)(void*));

必须做的是将void (callback)(void*)转换为上面的一个typedef。

1 个答案:

答案 0 :(得分:2)

嗯,施法应该有效。 C标准允许在函数指针类型之间进行转换,唯一不应该做的是通过具有错误原型的函数指针调用函数,即在调用之前转换回正确的原型,以避免未定义的行为。

为了便于阅读,我们首先简化一下你的数组:

modbus_read_t*  M_callbacks_r[2];
modbus_write_t* M_callbacks_w[2];
system_read_t*  P_callbacks_r[2];
system_write_t* P_callbacks_w[2];

我不知道为什么你typedef编辑了函数类型而不是函数指针类型,但我会继续使用它。

现在可以按如下方式实现registerCallback

void registerCallback(int systemType,int operationType, void (*callback)()) {
  // .. determine array by system type and operation type
  M_callbacks_r[0] = (modbus_read_t*)callback;
}

我从callback原型中删除参数的原因是,在标准C中,空参数列表不传达有关预期参数的信息(与C ++相反,它明确表示“无参数”)。这样就可以在不需要强制转换的情况下注册回调。

正如您在评论中提到的那样,您正在构建-Wstrict-prototypes -Werror。因此,空参数列表不适合您。因此,您只能像这样定义registerCallback

void registerCallback(int systemType,int operationType, void (*callback)(void))

请注意参数列表中的显式void。在将回调函数传递给registerCallback并将其强制转换回函数本身时,您需要转换回调函数。

registerCallback(type, op, (void(*)(void))func_cb);

附注:POSIX系统上保留_t后缀。为了便携,最好不要用它来命名你的类型。