为什么我可以使用static_cast使用void *但不能使用char *

时间:2016-09-22 18:51:17

标签: c++ casting reinterpret-cast strict-aliasing static-cast

我知道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*可以获得什么?这与严格的别名问题有关吗?

2 个答案:

答案 0 :(得分:0)

一般来说,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 :(得分:0)

您的问题实际上有两个部分:

  1. 我应该使用static_castreinterpret_cast来处理指向对象的基础位模式的指针而不关心对象类型吗?
  2. 如果我应该reinterpret_cast使用void*char*来解决此基础位模式?
  3.   

    static_cast:使用隐式转换和用户定义转换的组合在类型之间进行转换

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

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

    它利用隐式演员:

      

    指向任何(可选的cv限定的)对象类型T的prvalue指针可以转换为prvalue指针(相同的cv-qualified)void。结果指针表示内存中与原始指针值相同的位置。如果原始指针是空指针值,则结果是目标类型的空指针值。 *

    然而,从T类型的指针到char*没有隐式转换。因此,实现该演员表的唯一方法是使用reinterpret_cast

      

    reinterpret_cast:通过重新解释基础位模式

    在类型之间进行转换

    因此,当您转换为void*char*时,如果您希望使用基础位模式,那么在回答问题的 1 部分时,应该使用reinterpret_cast,因为它的使用表示读者与基础位模式之间的转换。

    接下来让我们将void*char*进行比较。这两者之间的决定可能更依赖于应用程序。如果要使用基础位模式的标准库函数,只需使用函数接受的类型:

      {li> void*用于mem库中提供的cstring函数
    • readwrite使用char*作为输入

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