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