将空*参数转换为各种类型的参数是UB吗?

Is it UB to cast void* param to various types?

本文关键字:参数 UB 类型 种类 转换 将空      更新时间:2023-10-16
void WorkHorse(void* ptr, int tag) {
if (SomeFunction(tag)) {
Foo* foo_ptr = (Foo*)ptr;
// do stuff
} else {
Bar* bar_ptr = (Bar*)ptr;
}
}

我知道这通常是一个糟糕的设计,但很好奇它在技术上是否是 UB。

void* 参数转换为各种类型的参数是 UB 吗?

否,将void*强制转换为指向对象类型的指针不是 UB。如果是这样,那么void*将几乎毫无用处。

但是,在某些情况下,通过转换后的指针进行间接可能是 UB;通常是当地址不包含适当类型的对象时。

正如你所指出的,使用这样的void*通常是糟糕的设计,只有在与某些 C API 交互时才需要。

你代码中最让我讨厌的部分是转换的风格,而不是对转换所做的。我宁愿使用static_cast而不是 C 样式的演员表。使用足以完成预期作业的最弱工具,为编译器指出可疑代码(即关于可能的错误发出警告(提供了最大的回旋余地。

使用static_cast的一个附带好处是,您的问题的答案直接位于static_cast转化页面@cppreference.com 上。查看第 10 点,该点以以下内容结尾。

将任何指针转换为指向 void 的指针,然后再转换回指向原始(或更多符合 cv 条件(类型的指针,将保留其原始值。

如果您已将Foo*转换为void*以获取作为ptr传入的值,则static_cast返回到Foo*将恢复原始值。取消引用原始值是可以的,只要它没有成为悬而未决的指针。

为了公平对待 C 型转换,在这种情况下,使用 C 样式转换或static_cast时,您确实会得到相同的结果。您可以从显式投射页面 @ cppreference.com 开始获取文档 - 因为该页面链接到static_cast页面。;)


此外,除非 API 要求,否则不要执行这些转换。似乎在这一点上是一致的,所以对我来说只是一个脚注。