我想知道reinterpret_cast是如何在幕后工作的。我正在从一本书中学到它,但我只是不明白。 例如。假设我有以下部分代码:
int a = 255;
char *pChar = reinterpret_cast<char*>(&a);
或
std::string str = "Hello";
char *pChar = reinterpret_cast<char*>(&str);
pChar在两个例子中指出了什么,为什么当我尝试打印其内容时我看不到任何东西,当然reinterpret_cast如何工作?
修改 我知道reinterpret_cast使用起来非常危险,只想用它将字节直接写入内存块的二进制文件中。 我不明白的是,当我有一个
int a = 255; (00 00 00 FF in memory)
我希望将变量a
视为一系列字节,char *:
char *pChar = reinterpret_cast<char*>(&a);
pChar会指向变量a
(00 00 00 FF)的各个字节吗?
所以,当我想写入pChar
指向的二进制文件时:
a_file.write(reinterpret_cast<char*>(&a), sizeof(a));
它写出变量a
的各个字节,对吗?
答案 0 :(得分:6)
它在运行时没有做任何事情。 Cpp reference:
与static_cast不同,但与const_cast不同,是reinterpret_cast 表达式不会编译为任何CPU指令。这纯粹是一个 编译器指令,指示编译器处理序列 表达式的位(对象表示),就像它具有类型一样 NEW_TYPE。
你的转换都非常危险,因为第一个指针指向一个int,它可能在内存中表示为00 00 00 FF
,因此不会打印任何东西,因为00 ==&#39; \ 0&# 39;,这是字符串结尾的char。这假设您使用的是大端机器。如果这是一个用非零值填充所有字节的int
,那么您将无限期地读取该位置的末尾。
第二个告诉编译器将string
所在的位置视为char*
,这不是实际字符串内容的起始地址,而是实现定义的结构,其中包含大小,容量和指针变量或小字符串optmization的字符串表示。由于大小和容量通常为64位宽,并且大小和容量可能都小于2 ^ 32,因此您可能会遇到零字节,因此不会打印任何内容。再一次,如果没有意外的零字节,你的读取将无限期地结束。
解决OP的编辑:
根据链接的cpp-reference网站的第5部分
任何指向T1类型对象的指针都可以转换为指向对象的指针 另一种类型cv T2。这完全等同于static_cast(static_cast(expression))(这意味着如果T2&#39; s 对齐要求并不比T1的值更严格 指针不会改变并返回结果指针的转换 原始类型产生原始值)。无论如何, 如果允许的话,结果指针只能被安全地解除引用 类型别名规则(见下文)
如下所述:
指向动态类型为的对象的指针或引用 DynamicType是reinterpret_cast(或C样式转换)到指针或 引用不同类型AliasedType的对象,总是强制转换 成功,但结果指针或引用可能只用于 如果满足以下条件之一,则访问该对象:...
AliasedType是char,unsigned char或std :: byte:这允许 检查任何对象的对象表示作为数组 字节。 ...
,指针应指向a
开始的地址。
答案 1 :(得分:0)
pChar在两个例子中都指出了什么?
它们将指向存储这些变量的内存的第一个字符。
为什么当我尝试打印其内容时,我无法看到任何内容
你可能以错误的方式做到这一点。您不能将它们打印为以空字符结尾的字符串(例如,a
的内部表示包含0,这将被视为终止零。)
您可以这样打印:
for (size_t i=0; i<sizeof(int); i++) {
printf("%02x ", pChar[i]);
}
printf("\n");
这将以十六进制打印a
的字符值。这样,您就会看到ff 00 00 00
(假设您使用的是小端机器)。
您可以对std::string
执行相同的操作。您将看到std::string
的内存表示。
(您可以使用&#34;%c&#34;将内容打印为char。如果将stdout重定向到文件,您将在文件中看到变量的内部表示。
当然reinterpret_cast如何运作?
它只是重新解释它的参数,假装它有另一种类型。不涉及运行时成本(注意:这种解释非常简化)。
pChar是否指向变量a(00 00 00 FF)的各个字节?
是的,假设char是一个字节,而你是一个大端机器。
它写入变量a,右
的各个字节
是的,但可能你也可以在没有任何reinterpret_cast的情况下做同样的事情,这里不需要它(假设a_file.write
的第一个参数是void *
)