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

问题描述 投票:3回答:2

stackoverflow上有很多关于读取和写入unsigned char的帖子。这些帖子建议使用reinterpret_castunsigned 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();
c++ c++17
2个回答
3
投票

reinterpret_cast从不“需要”; reinterpret_cast可以做的任何事情都可以通过C风格演员同样做得很好。

存在特殊的强制转换语法,因为需要reinterpret_cast的东西往往是危险的东西,因此可能应该注意代码中的那些点。 reinterpret_cast还可以防止意外移除const,C型演员可以让你做。


2
投票

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

C ++是一种打字语言。尽管有不同的大小,unsigned charchar是分开的类型。指向unsigned char的指针和指向char的指针也是不同的类型。

C ++语言具有类型安全性。类型系统旨在通过禁止使用一个对象来防止您犯错,就像它是另一个不相关的类型一样。从某些类型到其他类型的隐式转换允许从另一类型的对象创建一种类型的新对象1。此外,还有明确的转换,当没有隐式转换时,它们允许相同的转换。其中一个显式转换允许完全绕过类型系统:重新解释转换。

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

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

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

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


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

2另请注意,如果没有符合类型系统的转换,C风格的强制转换(char*)buff将重新解释转换。它也会进行const转换,重新解释转换不行。这使得C风格的演员阵容更加不安全。通常建议明确使用您打算使用的强制转换类型(静态,重新解释或常量转换)而不是C样式强制转换,它执行一个或多个组合,具体取决于哪个恰好适合。

如果没有reinterpret_cast,有人可以发布一个无效的代码吗?

如果你从你的程序中删除reinterpret_casts,那么它将是不正确的。该标准并不保证它会起作用。如果使用不扩展语言的编译器,它可能不起作用。例如,GCC refuses to compile

当然,任何需要reinterpret_cast的程序都可以重写为使用C样式转换,因为2。


附:通常情况下,更好的设计可以避免演员阵容。在这种情况下,您可以使用std::basic_ofstream<unsigned char>std::basic_ifstream<unsigned char>,并且不需要演员表。

© www.soinside.com 2019 - 2024. All rights reserved.