将指针传递给struct,传递void指针并转换为struct

时间:2017-07-11 01:47:07

标签: c++

我正在研究具有这种模式的遗留代码库:

struct sometype_t { /* ... */ };

int some_method(void *arg1) { // void pointer
    ((sometype_t*)arg1)->prop1; // cast
}

是否存在使用sometype_t *代替void *不安全的(常见)情况?

int some_method(sometype_t *arg1) {
    arg1->prop1;
}

指针不会通过ABI传递到第三方库;它完全保留在我们拥有的C ++代码中。

2 个答案:

答案 0 :(得分:2)

它通常不是一个好的选择,但是我唯一知道这种情况的唯一情况是,如果你想在不使用模板的情况下将状态回调传递给函数:

void takes_callback(void(*f)(void*), void * data);

基本上,要点是因为你没有使用模板,你必须修复你接受的函数签名(当然,它可以并且经常会采取其他参数并返回一些东西)。如果您只是使用自己的参数调用该函数,则该函数只能通过全局变量保持调用之间的状态。因此,takes_callback的合同承诺以f作为参数调用data

因此,如果您想在此类API中使用some_method作为回调,则必须使用void*并在内部执行转换。显然,你在这里抛弃了类型安全,如果你碰巧用takes_callback来呼叫&somemethod并指向任何不是sometype_t你有UB的东西。

拥有C ABI是避免模板的一个原因,但它并不是唯一的模板。也许他们担心代码膨胀,或者想要将实现保留在.so中,以便可以升级版本而无需重新编译等。

答案 1 :(得分:0)

立即想到的一个明显的常见场景是来自C标准库的某些函数的回调。

例如,为std::qsort编写比较回调的正确方法是使用两个const void *参数声明该函数,然后将它们转换为回调内适当的特定指针类型。

使用特定类型的指针替换这些const void *参数只会阻止代码编译。