3

stackoverflow 上有很多关于读写无符号字符的帖子。这些帖子推荐使用reinterpret_castfor cast from unsigned char*to 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();
4

2 回答 2

3

reinterpret_cast从不“需要”;任何reinterpret_cast可以做的事情都可以通过 C 风格的演员来同样出色地完成。

存在特殊的强制转换语法是因为需要的东西reinterpret_cast往往是危险的东西,因此应该注意代码中的这些点。reinterpret_cast还可以防止意外删除const,C 风格的演员将允许您这样做。

于 2019-04-15T00:14:06.433 回答
2

为什么将 unsigned char* 转换为 char* 需要 reinterpret_cast?

C++ 是一种类型化语言。尽管有不同的大小,unsigned char并且char是不同的类型。指向unsigned char和指向的指针char也是不同的类型。

C++ 语言具有类型安全性。类型系统旨在通过禁止将一个对象用作另一种不相关类型的对象来防止您犯错误。存在从某些类型到其他类型的隐式转换,这允许从另一种类型的对象创建一种类型的新对象1 。此外,还有显式转换,在不存在隐式转换时允许相同的转换。其中一种显式转换允许完全绕过类型系统:重新解释强制转换。

1同样,您可以将引用转换为其他类型的新引用。

char并且unsigned char不相关。指向一个的指针不能隐式转换为指向另一个的指针。当参数具有另一种类型时,将一个作为参数传递是不正确的。如果您明确告诉编译器忽略类型系统,那么它不会保护您免受使用错误类型的潜在错误。在这种情况下,重新解释是故意的,并且(据我所知)不是一个错误。正是这些有意的重新诠释,才是重新诠释铸造存在的原因。

我想知道为什么需要它,因为这两种类型的大小相同。

类型的含义并不完全由类型的大小来描述。


请注意,重新解释强制转换是不安全的。在处理重新解释的指针/引用时必须遵循许多规则,违反任何这些规则都会导致未定义的行为。仅仅因为这里可能是正确的,不要假设每次遇到类型不匹配时都可以使用重新解释转换。

2另请注意(char*)buff,如果不存在符合类型系统的转换,C 样式转换将重新解释转换。它还将执行 const 强制转换,而重新解释强制转换不会。这使得 C 风格的强制转换更加不安全。通常建议显式使用您打算使用的转换类型(静态、重新解释或 const 转换)而不是 C 样式转换,后者执行其中一个或组合,具体取决于恰好适合。

有人可以发布一个没有 reinterpret_cast 就无法工作的代码吗?

如果你reinterpret_cast从你的程序中删除 s,那么它将是不正确的。该标准不保证它会起作用。如果您使用不扩展语言的编译器,它可能无法正常工作。例如,GCC 拒绝编译.

当然,由于2reinterpret_cast ,任何需要的程序都可以重写以使用 C 风格转换。


PS 尽可能避免强制转换通常是一个更好的设计。在这种情况下,您可以使用std::basic_ofstream<unsigned char>and std::basic_ifstream<unsigned char>,并且不需要强制转换。

于 2019-04-15T00:29:05.540 回答