为什么将无符号字符* 转换为字符*需要reinterpret_cast?
Why does casting unsigned char* to char* require reinterpret_cast?
在stackoverflow上有很多关于读取和写入无符号字符的帖子。这些帖子建议使用reinterpret_cast
从unsigned char*
到char *
进行铸造。我想知道为什么需要它,因为两种类型的大小相同。
我在 Windows 和 Linux 上运行下面的代码,它工作正常(有或没有重新解释强制)。我错过了什么吗?有人可以发布一个没有reinterpret_cast
就不起作用的代码吗?请注意,我说的是unsigned char
(不是unsigned int
)。
#include <iostream>
#include <fstream>
std::ofstream os;
unsigned char *buff = new unsigned char[3]{ 0xe4, 0xe1, 0xd4 };
os.open("image.jpg", std::ios::out | std::ios::binary);
os.write(reinterpret_cast<char*>(buff), 3 * sizeof(unsigned char));
// or: os.write((char*)(buff), 3 * sizeof(unsigned char));
os.close();
std::ifstream file;
memset(buff, 0, 3 * sizeof(unsigned char));
file.open("image.jpg", std::ios::in | std::ios::binary);
file.read(reinterpret_cast<char*>(buff), 3 * sizeof(unsigned char));
//or: file.read((char *)buff, 3 * sizeof(unsigned char));
file.close();
reinterpret_cast
从来都不是"需要"的;reinterpret_cast
能做的任何事情都可以通过C风格的演员表同样出色地完成。
特殊强制转换语法的存在是因为需要reinterpret_cast
的东西往往是危险的东西,因此可能应该注意代码中的这些点。reinterpret_cast
还可以防止意外删除const
,这是 C 样式转换将允许您这样做。
为什么将无符号字符* 转换为字符*需要reinterpret_cast?
C++是一种类型化语言。尽管大小不同,但unsigned char
和char
是不同的类型。指向unsigned char
的指针和指向char
的指针也是单独的类型。
C++语言具有类型安全性。类型系统旨在通过禁止使用一个对象来防止您犯错误,就好像它是另一个不相关的类型一样。存在从某些类型到其他类型的隐式转换,这允许从另一种类型的对象创建一种类型的新对象1。此外,还有显式转换,当不存在隐式转换时,这些转换允许相同的转换。其中一个显式转换允许完全绕过类型系统:重新解释强制转换。
1同样,您可以将引用转换为其他类型的新引用。
char
和unsigned char
没有关系。指向一个的指针不能隐式转换为指向另一个的指针。当参数具有另一种类型时,将一个作为参数传递是格式不正确的。如果您显式告诉编译器忽略类型系统,那么它将无法保护您免受使用错误类型的潜在错误。在这种情况下,重新解释是故意的,并且(据我所知)不是错误。正是这些有意的重新诠释,才是重新诠释选角存在的原因。
我想知道为什么需要它,因为两种类型的大小相同。
类型的含义并不完全由类型的大小来描述。
请注意,重新解释强制转换是不安全的。在处理重新解释的指针/引用时,必须遵循许多规则,违反这些规则中的任何一个都会导致未定义的行为。仅仅因为它在这里可能是正确的,所以不要假设每次遇到与类型不匹配时都可以使用重新解释转换。
2另请注意,如果不存在符合类型系统的转换,则 C 样式转换(char*)buff
将重新解释转换。它还将进行常量铸造,而重新解释铸造则不行。这使得C型铸件更加不安全。通常建议显式使用您打算使用的强制转换类型(静态、重新解释或 const 强制转换),而不是 C 样式强制转换,后者执行其中一种或组合,具体取决于恰好适合哪种类型。
有人可以发布一个没有reinterpret_cast就无法工作的代码吗?
如果从程序中删除reinterpret_cast
,则其格式不正确。该标准不保证它会起作用。如果您使用的编译器不扩展语言,则可能无法正常工作。例如,GCC 拒绝编译。
当然,任何需要reinterpret_cast
的程序都可以重写以使用 C 样式转换来代替它,因为2。
附言通常,在可能的情况下避免铸造是一种更好的设计。在这种情况下,您可以使用std::basic_ofstream<unsigned char>
和std::basic_ifstream<unsigned char>
,并且不需要强制转换。
- C++字符*缓冲区的大小
- HEX值到wchar_t字符(UTF-8)的转换
- 为什么 Serial.println(<char[]>);返回随机字符?
- 我的字符计数代码计算错误.为什么
- 字符串-C++后显示的随机字符
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 如何在C++中从字符串中分割字符
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 指向指向字符数组的指针数组的指针
- 如何用转义符替换字符串中的所有特殊字符
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 比较字符数组
- 将字符指针十六进制转换为字符串并保存在文本文件C++中
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 如何在C++中确定文本文件中的元素是字符还是数字
- 如何将一个ostringstream十六进制字符串字符对转换为单个unit8t等价的二进制值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++中无符号字符溢出
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret