为什么C样式转换工作但reinterpret_cast不工作​​?

时间:2012-08-18 18:50:57

标签: c++ c casting reinterpret-cast

所以我有一个两个char数组

unsigned char v[2];

我想将v [0]的值显示为0到255之间但

的数字
cout << v[0] << endl; //prints some garbage

cout << (void*)v[0] << endl; //prints the right thing but in hex

所以我试过

cout << (int)v[0] << endl;

printf("%d\n", v[0]);

这显示了我想要的东西,但我完全不喜欢它。我根本不明白的是为什么这不起作用:

cout << reinterpret_cast<int>(v[0]) << endl; //compiler error

6 个答案:

答案 0 :(得分:22)

(以外行人的术语)reinterpret_cast用于将对象的位解释为实现定义方式中的另一种类型。你不希望这样:你想要一个转换(从char到int)。请改用static_cast

reinterpret_cast列出{{1}}的所有可能用途;这不是其中之一。)

答案 1 :(得分:14)

cout << v[0] << endl; // prints some garbage

不是垃圾,而是v [0]中的值表示的字符。

cout << (void*)v[0] << endl;

这会将v[0]中的值“转换”为指针(未定义的行为,因为它不是一个开头的指针),并将该指针的值打印为十六进制值。

cout << (int)v[0] << endl;

这会将v[0]中的值转换为int(定义良好;只需将其提升为int)并显示该值。

正如其他人所提到的,

reinterpret_cast对它能做什么有一些限制。正确的答案是使用static_cast<int>

cout << static_cast<int>(v[0]) << endl;

答案 2 :(得分:6)

  • reinterpret_cast:“...允许转换任何整数类型 进入任何指针类型,反之亦然。“仅用于转换 可以指向正确指针类型的东西(一个 unsigned char显然不能成为除了之外的任何指针 8位系统)。

  • static_cast:如果要将类型转换为其他类型,请使用此选项 type(如float到int,或unsigned char到int)。

cout尝试将无符号字符作为ASCII字符代码打印,因此通过static_cast<int>(v[0])转换为int是正确的做法。

答案 3 :(得分:3)

您使用reinterpret_cast的方式是尝试将char读取为int,并且它们的大小不同。

答案 4 :(得分:3)

reinterpret_cast将指针类型的值转换为其他指针类型值或整数值,反之亦然,以便允许取消引用目标指针值。但是,您尝试将一个整数类型值转换为另一个整数类型值。那不行。 reinterpret_cast支持引用类型的转换,这相当于使用后续解引用转换的相应指针值。所以看起来你想做

// NOTE: THIS IS UNDEFINED BEHAVIOR
cout << reinterpret_cast<int&>(v[0]) << endl; 

这是格式良好的,但是将unsigned char重新解释为整数对象,这不能保证工作(可能的问题包括从存储的无效对齐到不兼容的大小 - 1个字节对4个字节)。你可以通过(int)v[0]演员来解决这些问题,我认为这很好。您还可以说+v[0],它会自动将值提升为(已签名或未签名)int

答案 5 :(得分:0)

正如其他人所说,

static_cast会做正确的事。它比C风格的强制转换弱,因此不太可能造成破坏并导致不确定的行为。

reinterpret_cast也比C风格的演员阵容弱,但严格强于static_cast; static_cast可以执行reinterpret_cast无法做到的事情。你遇到过其中一个。

reinterpret_cast旨在允许您获取一种类型的值,将它们存储为另一种类型的值,然后返回原始类型。您可以这样做转换beteen整数和兼容的指针类型。您可以使用它将一种指针类型转换为另一种指针类型,然后再返回。

通常,reinterpret_cast会将您转换为“持有”值,并且该持有值最多是实现定义,并且经常使用它是未定义的行为。

所以你要避免使用它,除非你真的真的是这个意思。

char转换为int并不是通常需要重新解释的问题。

static_cast<int>(some_char)会将char升级为int,并为您提供适当的价值。

但是,在某些情况下,我发现static_cast 太强大了。它可以进行不安全的指针转换,并计为显式转换。

这两个都可以掩盖错误。

您可以按如下方式编写严格较弱的演员:

template<class T, class U>
T implicit_cast( U&& u ) { return std::forward<U>(u); }

现在你可以

std::cout << implicit_cast<int>(v[0]) << std::endl;

并且你得到的行为非常类似于调用带有int参数的char函数,我相信这就是你想要的。

这里出了什么问题?好吧,std::cout是一个流,并且流注意传递的类型。打印char类型就像它们是'a``样式字符一样,而不是它们是小整数。

为了将char视为小整数,您必须将其转换为另一种整数类型。

char*也是如此;它们被视为char的空终止缓冲区的指针,如"hello world",而不像其他指针。