为什么我不能reinterpret_cast uint到int? [英] Why can't I reinterpret_cast uint to int?
问题描述
这里是我想做的:
const int64_t randomIntNumber = reinterpret_cast< int64_t> (randomUintNumber);
其中randomUintNumber类型为 uint64_t
。
Where randomUintNumber is of type uint64_t
.
错误是(MSVC 2010):
The error is (MSVC 2010):
错误C2440:'reinterpret_cast':无法转换从'const uint64_t'
到'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
相同的值, / p>
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;
如果这导致编译器警告,或者如果你只是想更加明确, / p>
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
小于2 63 。否则,结果是实现定义的,但我希望所有已知的实现, int64_t
将定义它做明显的事情:结果等于输入模2 64 。
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
。
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,你可能会这样写:
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
中的位模式是<$ c $的值的有效表示, c> 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.
这篇关于为什么我不能reinterpret_cast uint到int?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!