13

所以我有一个两个字符数组

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
4

6 回答 6

22

(通俗地说)reinterpret_cast用于以实现定义的方式将对象的位解释为另一种类型。您不希望这样:您想要转换(从 char 到 int)。改为使用static_cast

(所有可能的用途reinterpret_cast都列在5.2.10中;这不是其中之一。)

于 2012-08-18T18:53:35.747 回答
15
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;
于 2012-08-18T18:59:16.920 回答
6
  • reinterpret_cast:“...允许将任何整数类型转换为任何指针类型,反之亦然。” 仅使用它来将可能是指针的内容转换为正确的指针类型(无符号字符显然不能成为 8 位系统以外的任何指针)。

  • static_cast:当您想将一个类型转换为另一种类型时使用此选项(例如将 float 转换为 int,或将 unsigned char 转换为 int)。

cout尝试将 unsigned char 打印为 ASCII 字符代码,因此转换为 int viastatic_cast<int>(v[0])是正确的做法。

于 2012-08-18T19:00:15.190 回答
3

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

于 2012-08-18T18:55:16.140 回答
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

于 2012-08-19T00:41:35.637 回答
0

static_cast正如其他人所指出的,将做正确的事。它比 C 风格的强制转换弱,因此不太可能造成破坏并导致未定义的行为。

reinterpret_cast也弱于 C 风格的强制转换,但并不严格地强于static_cast; 有些事情static_cast可以做而reinterpret_cast不能。你遇到了其中之一。

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

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

所以你要避免使用它,除非你真的是认真的。

将 a 转换char为 anint通常不需要重新解释。

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


但是,在某些情况下,我觉得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;

你得到的行为非常像调用一个intchar参数的函数,我相信这就是你想要的。


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

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

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

于 2017-07-24T12:58:44.120 回答