c++ - 为什么我不能将 uint 重新解释为 int?

标签 c++ type-conversion reinterpret-cast

这是我想做的:

const int64_t randomIntNumber = reinterpret_cast<int64_t> (randomUintNumber);

其中 randomUintNumber 的类型为 uint64_t .

错误是(MSVC 2010):

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 的用途吗?

最佳答案

因为这不是 reinterpret_cast 的用途。 reinterpret_cast 允许的所有转换都涉及指针或引用,但整数或枚举类型可以是 reinterpret_cast 自身的异常(exception)。这一切都在标准中定义,[expr.reinterpret.cast]

我不确定您要在这里实现什么,但如果您希望 randomIntNumber 具有与 randomUintNumber 相同的值,那么就这样做

const int64_t randomIntNumber = randomUintNumber;

如果这会导致编译器警告,或者您只想更明确,那么:

const int64_t randomIntNumber = static_cast<int64_t>(randomUintNumber);

如果 randomUintNumber 小于 263,则转换结果与输入具有相同的值。否则结果是实现定义的,但我希望所有具有 int64_t 的已知实现都会定义它来做显而易见的事情:结果相当于输入模 264 .


如果您希望 randomIntNumber 具有与 randomUintNumber 相同的位模式,那么您可以这样做:

int64_t tmp;
std::memcpy(&tmp, &randomUintNumber, sizeof(tmp));
const int64_t randomIntNumber = tmp;

由于 int64_t 保证使用二进制补码表示,您会希望实现定义 static_cast 具有与此相同的结果uint64_t 的值超出范围。但在标准 AFAIK 中实际上并不能保证。

即使 randomUintNumber 是一个编译时常量,不幸的是这里 randomIntNumber 不是一个编译时常量。但是,编译时常量有多“随机”? ;-)

如果您需要解决这个问题,并且您不相信实现将超出范围的无符号值转换为有符号类型是明智的,那么可以这样:

const int64_t randomIntNumber = 
    randomUintNumber <= INT64_MAX ? 
        (int64_t) randomUintNumber :
        (int64_t) (randomUintNumber - INT64_MAX - 1) + INT64_MIN;

现在,我赞成在可能的情况下编写真正可移植的代码,但即便如此,我认为这已接近妄想症。


顺便说一句,你可能会想这样写:

const int64_t randomIntNumber = reinterpret_cast<int64_t&>(randomUintNumber);

或等效:

const int64_t randomIntNumber = *reinterpret_cast<int64_t*>(&randomUintNumber);

这并不能完全保证工作,因为虽然它们存在的地方 int64_tuint64_t 保证是相同大小的有符号类型和无符号类型,它们实际上并不能保证是标准整数类型的有符号和无符号版本。因此,此代码是否违反严格别名是特定于实现的。违反严格别名的代码具有未定义的行为。以下确实违反了严格的别名,只要 randomUintNumber 中的位模式是 long long 值的有效表示,则可以:

unsigned long long x = 0;
const long long y = reinterpret_cast<long long &>(x);

所以在 int64_tuint64_tlong longunsigned long long 的 typedef 的实现中,那么我的reinterpret_cast 没问题。与实现定义的超出范围值到有符号类型的转换一样,您会期望实现的明智之举是让它们对应有符号/无符号类型。因此,就像 static_cast 和隐式转换一样,您希望它可以在任何合理的实现中工作,但实际上并不能保证。

关于c++ - 为什么我不能将 uint 重新解释为 int?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14623266/

相关文章:

c++ - 请一点 C++ 帮助(重复输出)

c++ - 科学计数法 C++ 中的字符串到双重转换

c++ - 编译器从 `long` 转换时,`double` 和 `int ` 相同

c++ - 用更好的替代品替换 reinterpret_cast?

c++ - 包含文件未被识别,即使它们位于正确的目录中?

c++ - 包装 Eigen 的张量类以创建动态秩张量?

c++ - header 中的字符串原型(prototype)需要 iostream?

type-conversion - 为什么 GLib 的 GValue 系统不包括字符串到数字的转换?

c++ - 用 C++ : legal or not? 重新解释这个

c++ - 签名/未签名别名规则是否按预期工作?