[英]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.