reinterpret_cast如何处理不相关的类?

时间:2016-09-10 17:51:44

标签: c++ pointers reinterpret-cast

以下代码中的前两行输出是两个空白行,第三行和第四行是两个不相等的大数字,如: 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的返回是什么。谢谢!

2 个答案:

答案 0 :(得分:5)

您正在进行未定义的行为。编译器可以自由地生成完全可以执行任何操作的代码,包括创建一个机器人,以便及时回到K&amp; R的父母那里,并在早上吃药以防止C首先被发明。

在上面的前两种情况中,您的编译器会将int的字节和值为double的{​​{1}}解释为以空字符结尾的字符数组,然后查看它作为0长度的缓冲区,所以什么都不打印。

在第二组0强制转换的情况下,它给出了从(int)得到的指针值的较低sizeof(int)字节的整数表示。

这些都不令人惊讶,但这些都不能依赖。从严格别名到优化,编译器可以在您处理未定义的行为时做一些疯狂的事情,即使您没有附加时间机器或机器人,UB的效果也可能在UB运行的代码运行之前发生

答案 1 :(得分:1)

代码reinterpret_cast<char*>(pa)生成一个指向A类型对象的指针。由于A是标准布局类,因此可以通过这种方式明确定义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)与之前的情况类似。