为什么我不能reinterpret_cast uint到int? [英] Why can't I reinterpret_cast uint to int?

查看:300
本文介绍了为什么我不能reinterpret_cast uint到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆