reinterpret_cast 如何处理不相关的 class?

How reinterpret_cast works when it comes to to irrelevant class?

下面代码输出的前两行是两个空行,第三、四行是两个不相等的大数,比如: 19147336 19147192

class A {
public:
    A() : m_i(0) { }
protected:
    int m_i;
};

class B {
public:
    B() : m_d(0.0) { }
protected:
    double m_d;
};

int main() {
    A *pa = new A;
    B *pb = new B;
    std::cout << reinterpret_cast<char*>(pa) << std::endl;
    std::cout << reinterpret_cast<char*>(pb) << std::endl;
    std::cout << (int)reinterpret_cast<char*>(pa) << std::endl;
    std::cout << (int)reinterpret_cast<char*>(pb) << std::endl;

    return 0;
}

我想知道上面代码中reinterpret_cast的return到底是什么。谢谢!

您正在进行未定义的行为。编译器可以自由地生成几乎可以做任何事情的代码,包括创建一个机器人回到过去,用事后避孕药来扑灭 K&R 的 parents,以防止 C 被发明出来。

在上面的前两种情况下,您的编译器将值 0intdouble 的字节解释为 nul-terminated 字符数组, 并将其视为 0 长度缓冲区,因此不打印任何内容。

在第二组 (int) 转换案例中,它为您提供了从 new.[=16= 获得的指针值的较低 sizeof(int) 字节的整数表示]

这些都不足为奇,但都不可靠。从严格的别名到优化,当您从事未定义的行为时,编译器可以做一些疯狂的事情,即使您没有附加时间机器或机器人,UB 的影响也会在带有 UB 的代码运行之前发生.

代码 reinterpret_cast<char*>(pa) 产生一个指向类型 A 的对象的指针。因为 A 是标准布局 class,所以以这种方式访问​​ A 的第一个数据成员是明确定义的。

  • std::cout << reinterpret_cast<char*>(pa)。您正在调用 std::operator<< 的重载,它采用 char * 第二个参数。该函数表示输出存储在该位置的字符串。由于该位置的第一个 char 的值为 0(因为值 0 的 int 保证由零值字节组成),这是明确定义的并且输出一个空字符串。
  • std::cout << reinterpret_cast<char*>(pb)double 的表示是实现定义的。在常见的 IEEE754 系统上,0.0 的所有位都为零,因此您会像以前一样得到一个空白字符串。在其他系统上,这将取决于它们对数字的表示发生了什么(如果没有空字节,则可能是未定义的行为)。
  • std::cout << (int)reinterpret_cast<char*>(pa) 此代码将地址转换为 int。如果地址不能表示为 int(这可能发生在 64 位系统上),则会导致未定义的行为。否则你会得到一个代表地址的数字。
  • std::cout << (int)reinterpret_cast<char*>(pb) 与上例类似。