所以我有一个两个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
答案 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"
,而不像其他指针。