为什么我可以使用 static_cast With void* 而不是 With char*

Why can I use static_cast With void* but not With char*

我知道 reinterpret_cast 主要用于往返 char*

但我惊讶地发现 static_cast 可以用 void* 做同样的事情。例如:

auto foo "hello world"s;
auto temp = static_cast<void*>(&foo);
auto bar = static_cast<string*>(temp);

我们使用 reinterpret_castchar* 而不是 static_castvoid* 有什么好处?与严格的别名问题有关吗?

一般来说,static_cast 会强制转换任何两种类型,只要其中一种类型可以隐式 转换为另一种类型。这包括算术转换、向下转换、向上转换以及与 void*.

之间的转换

也就是说,如果此转换有效:

void foo(A a);
B b;
foo(b);

那么static_cast<B>(a)static_cast<A>(b)也都有效

由于任何指针都可以隐式转换为 void*,因此您的行为很奇怪。

reinterpret_cast 通过重新解释值的位模式来进行转换。正如您在问题中所说,通常是为了在不相关的指针类型之间进行转换。

是的,您可以通过 void* 在不相关的指针类型之间进行转换,方法是使用两个 static_cast:

B *b;
A *a1 = static_cast<A*>(b); //compiler error
A *a2 = static_cast<A*>(static_cast<void*>(b)); //it works (evil laugh)!

但这是在违反规则。如果您真的需要这个,请使用 reinterpret_cast

你的问题确实有两部分:

  1. 我应该使用 static_cast 还是 reinterpret_cast 来处理指向对象底层位模式的指针而不关心对象类型?
  2. 如果我应该使用 reinterpret_castvoid* 还是 char* 更适合解决这个底层位模式?

static_cast: Converts between types using a combination of implicit and user-defined conversions

在5.2.9[expr.static.cast]13标准中,其实给出了例子:

T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));

它利用隐式转换:

A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*

然而,没有从类型 T 的指针到 char* 的隐式转换。因此,完成该转换的唯一方法是使用 reinterpret_cast.

reinterpret_cast: Converts between types by reinterpreting the underlying bit pattern

因此,在回答问题的 1 部分时,当您转换为 void*char* 时,您希望使用底层位模式,应该使用 reinterpret_cast,因为它的使用表示 reader 转换 to/from 底层位模式。

接下来让我们比较一下 void*char*。这两者之间的决定可能更多地取决于应用程序。如果您打算将标准库函数与底层位模式一起使用,只需使用该函数接受的类型:

  • void*用于cstring库中提供的mem函数
  • read and write 使用 char* 作为输入

值得注意的是,特定于 C++ 的库更喜欢 char* 来指向内存。 作为 void* 保留内存似乎出于兼容性原因被保留为指针 here。因此,如果 cstring 库函数不会在您的基础位模式上使用,请使用 C++ 特定库行为来回答您问题的 2 部分:更喜欢 char* 而不是 void*.