繁体   English   中英

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

[英]Passing pointer to struct, vs. passing void pointer and casting to struct

我正在使用具有以下模式的旧式代码库:

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 ++代码中。

通常,这不是一个好选择,但是我知道真正有意义的唯一情况是,如果您希望将有状态回调传递给函数,而不使用模板:

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

基本上,要点是,由于您不使用模板,因此必须修复您接受的函数签名(当然,它可以并且经常确实接受其他参数并返回某些内容)。 但是,如果仅使用自己的参数调用该函数,则该函数只能通过全局变量保持两次调用之间的状态。 因此, takes_callback承诺以data作为参数调用f

因此,如果您想在这种API中使用some_method作为回调,则必须使其采用void* ,并在内部进行转换。 显然,您在这里丢弃了类型安全性,并且如果碰巧使用&somemethod和指向不是sometype_t任何东西的指针调用takes_callback ,则您拥有UB。

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

立即想到的显而易见的常见场景是C标准库中某些函数的回调。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM