static_cast与reinterpret_cast在将指针转换为指针时的区别

4

鉴于以下情况:

struct A
{
    int a;
};

struct B
{
    int b;
};

int main()
{
    A  a {1};
    A* p = &a;

使用static_castreinterpret_cast通过void*进行强制转换会得到相同的结果吗?即以下表达式之间是否有任何区别?
    static_cast      <A*> ( static_cast      <void*> (p) );
    reinterpret_cast <A*> ( reinterpret_cast <void*> (p) );

如果我们使用 static_castreinterpret_cast 将一个类的指针转换为另一个类的指针,这两个操作符之间有区别吗?以下表达式是否相同?
    static_cast      <B*> ( static_cast      <void*> (p) );
    reinterpret_cast <B*> ( reinterpret_cast <void*> (p) );
    reinterpret_cast <B*> (                           p  );

我可以在这之后使用B*指针来访问b成员吗?

1个回答

7

is there any difference between the following expressions?

static_cast      <A*> ( static_cast      <void*> (p) );
reinterpret_cast <A*> ( reinterpret_cast <void*> (p) );
不。

Are the following expressions the same?

static_cast      <B*> ( static_cast      <void*> (p) );
reinterpret_cast <B*> ( reinterpret_cast <void*> (p) );
reinterpret_cast <B*> (                           p  );

可以。

易于理解的方法是考虑reinterpret_cast从指针到指针的规定。 reinterpret_cast<T*>(ptr)的行为与static_cast<T*>(static_cast<void*>(ptr))完全相同 (为简单起见,我省略了cv限定符)。

当然,static_cast<T>(static_cast<T>(anything))等同于static_cast<T>(anything),因为外层转换总是恒等转换。


在此之后,我可以使用B*指针来访问b成员吗?

不可以。如果这样做,则程序的行为将未定义。


1
值得一提的是,从 pB* 的强制类型转换并不总是等同于先转换为 void* -- 这只适用于 OP 的示例。如果 AB 在层次上有关联,则指针值可以在转换过程中更改。此外,据我所知,从 A -> void -> B 的转换始终是未定义行为,无法进行解引用操作,而 A -> B 可以合法进行,前提是两种类型具有兼容的布局。 - Human-Compiler
我认为值得完整地提及这个标准: “8.5.1.10重新解释转换:7个对象指针可以显式转换为不同类型的对象指针。当对象指针类型的prvalue v被转换为对象指针类型“pointer to cv T”时,结果是static_cast<cv T*>(static_cast<cv void*>(v))。” - Mircea Ispas
@Human-Compiler AB之间存在层次关系,指针值可以作为强制类型转换的一部分而改变。如果是static_cast<A*>(b_ptr),那么是的。如果没有继承,那么这种转换将是不合法的。此外,从A -> void -> B转换在解引用时始终是未定义行为,而A -> B则可以是合法的,前提是两个类型具有布局兼容性。如果您指的是reinterpret_cast并且这些转换是指针,则这两者在所有方面都是相同的,并且无论布局兼容性如何,访问都是未定义的行为。如果您指的是static_cast,则后者可能是良好定义的。 - eerorika
关于“如果A和B在层次上相关,则指针值可以作为强制转换的一部分而更改”的技术问题,从技术上讲,在大多数类型转换中(即使不是层次结构静态或动态转换),指针值也可以更改,因为指针类型通常不需要具有相同的表示形式,除非在特定情况下。然而,在实践中,所有指针通常都具有相同的表示形式,例如在64位x86上。 - eerorika
@eerorika 给定 struct Coordinate{double x, double y, double z}; double *ptr1, *ptr2; Coordinate stSpaceCoord; 请问 ptr1 = static_cast<void*>(&stSpaceCoord);ptr2 = reinterpret_cast<void*>(&stSpaceCoord); 有什么区别吗?谢谢。 - John
@John 不,将 static_cast 和 reinterpret_cast 应用于 void*(或从 void* 转换)时没有任何区别。 - eerorika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接