Why can#39;t I reinterpret_cast uint to int?(为什么我不能将 uint 重新解释为 int?)
问题描述
这是我想做的:
const int64_t randomIntNumber = reinterpret_cast
其中 randomUintNumber 的类型为 uint64_t
.
Where randomUintNumber is of type uint64_t
.
错误是(MSVC 2010):
The error is (MSVC 2010):
错误 C2440:reinterpret_cast":无法从const uint64_t"转换to 'int64_t' 1> 转换是有效的标准转换,可以隐式执行,也可以使用 static_cast,C 风格演员表或函数式演员表
error C2440: 'reinterpret_cast' : cannot convert from 'const uint64_t' to 'int64_t' 1> Conversion is a valid standard conversion, which can be performed implicitly or by use of static_cast, C-style cast or function-style cast
为什么不编译?两种类型都有相同的位长,这不是 reinterpret_cast 的用途吗?
Why doesn't it compile? both types have the same bit length, isn't it what reinterpret_cast is intended for?
推荐答案
因为这不是 reinterpret_cast
的用途.reinterpret_cast
允许的所有转换都涉及指针或引用,但整数或枚举类型可以是 reinterpret_cast
自身的例外.这一切都在标准中定义,[expr.reinterpret.cast]
.
Because that's not what reinterpret_cast
is for. All the permitted conversions with reinterpret_cast
involve pointers or references, with the exception that an integer or enum type can be reinterpret_cast
to itself. This is all defined in the standard, [expr.reinterpret.cast]
.
我不确定您要在这里实现什么,但如果您希望 randomIntNumber
具有与 randomUintNumber
相同的值,那么就这样做
I'm not certain what you're trying to achieve here, but if you want randomIntNumber
to have the same value as randomUintNumber
, then do
const int64_t randomIntNumber = randomUintNumber;
如果这会导致编译器警告,或者您只想更明确,那么:
If that results in a compiler warning, or if you just want to be more explicit, then:
const int64_t randomIntNumber = static_cast<int64_t>(randomUintNumber);
如果 randomUintNumber
小于 263,则转换结果与输入具有相同的值.否则结果是实现定义的,但我希望所有具有 int64_t
的已知实现都会定义它来做显而易见的事情:结果相当于输入模 264.
The result of the cast has the same value as the input if randomUintNumber
is less than 263. Otherwise the result is implementation-defined, but I expect all known implementations that have int64_t
will define it to do the obvious thing: the result is equivalent to the input modulo 264.
如果您希望 randomIntNumber
具有与 randomUintNumber
相同的位模式,那么您可以这样做:
If you want randomIntNumber
to have the same bit-pattern as randomUintNumber
, then you can do this:
int64_t tmp;
std::memcpy(&tmp, &randomUintNumber, sizeof(tmp));
const int64_t randomIntNumber = tmp;
由于 int64_t
保证使用二进制补码表示,您会希望实现定义 static_cast
具有与此相同的结果uint64_t
的值超出范围.但在标准 AFAIK 中实际上并不能保证.
Since int64_t
is guaranteed to use two's complement representation, you would hope that the implementation defines static_cast
to have the same result as this for out-of-range values of uint64_t
. But it's not actually guaranteed in the standard AFAIK.
即使 randomUintNumber
是一个编译时常量,不幸的是这里 randomIntNumber
不是一个编译时常量.但是,编译时常量有多随机"?;-)
Even if randomUintNumber
is a compile-time constant, unfortunately here randomIntNumber
is not a compile-time constant. But then, how "random" is a compile-time constant? ;-)
如果您需要解决这个问题,并且您不相信实现将超出范围的无符号值转换为有符号类型是明智的,那么可以这样:
If you need to work around that, and you don't trust the implementation to be sensible about converting out-of-range unsigned values to signed types, then something like this:
const int64_t randomIntNumber =
randomUintNumber <= INT64_MAX ?
(int64_t) randomUintNumber :
(int64_t) (randomUintNumber - INT64_MAX - 1) + INT64_MIN;
现在,我赞成在可能的情况下编写真正可移植的代码,但即便如此,我认为这已接近妄想症.
Now, I'm in favour of writing truly portable code where possible, but even so I think this verges on paranoia.
顺便说一句,你可能会想这样写:
Btw, you might be tempted to write this:
const int64_t randomIntNumber = reinterpret_cast<int64_t&>(randomUintNumber);
或等效:
const int64_t randomIntNumber = *reinterpret_cast<int64_t*>(&randomUintNumber);
这并不能完全保证工作,因为虽然它们存在的地方 int64_t
和 uint64_t
保证是相同大小的有符号类型和无符号类型,它们实际上并不能保证是标准整数类型的有符号和无符号版本.因此,此代码是否违反严格别名是特定于实现的.违反严格别名的代码具有未定义的行为.以下确实不违反了严格的别名,只要 randomUintNumber
中的位模式是 long long
值的有效表示,则可以:
This isn't quite guaranteed to work, because although where they exist int64_t
and uint64_t
are guaranteed to be a signed type and an unsigned type of the same size, they aren't actually guaranteed to be the signed and unsigned versions of a standard integer type. So it is implementation-specific whether or not this code violates strict aliasing. Code that violates strict aliasing has undefined behavior. The following does not violate strict aliasing, and is OK provided that the bit pattern in randomUintNumber
is a valid representation of a value of long long
:
unsigned long long x = 0;
const long long y = reinterpret_cast<long long &>(x);
所以在 int64_t
和 uint64_t
是 long long
和 unsigned long long
的 typedef 的实现中,那么我的reinterpret_cast
没问题.与实现定义的超出范围值到有符号类型的转换一样,您会期望实现的明智之举是让它们对应有符号/无符号类型.因此,就像 static_cast
和隐式转换一样,您希望它可以在任何合理的实现中工作,但实际上并不能保证.
So on implementations where int64_t
and uint64_t
are typedefs for long long
and unsigned long long
, then my reinterpret_cast
is OK. And as with the implementation-defined conversion of out-of-range values to signed types, you would expect that the sensible thing for implementations to do is to make them corresponding signed/unsigned types. So like the static_cast
and the implicit conversion, you expect it to work in any sensible implementation but it is not actually guaranteed.
这篇关于为什么我不能将 uint 重新解释为 int?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么我不能将 uint 重新解释为 int?
基础教程推荐
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 从 std::cin 读取密码 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01