为什么我不能reintpret_cast uint到int?

Vio*_*ffe 17 c++ type-conversion reinterpret-cast

这就是我想要做的事情:

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

randomUintNumber的类型uint64_t.

错误是(MSVC 2010):

错误C2440:'reinterpret_cast':无法从'const uint64_t'转换为'int64_t'1>转换是一种有效的标准转换,可以隐式执行,也可以使用static_cast,C风格的转换或函数式转换

为什么不编译?两种类型都有相同的位长,是不是reinterpret_cast用于什么?

Ste*_*sop 26

因为那不是reinterpret_cast为了什么.所有允许的转换reinterpret_cast涉及指针或引用,但整数或枚举类型可以是reinterpret_cast自身.这都是在标准中定义的[expr.reinterpret.cast].

我不确定你在这里想要达到的目标,但是如果你想randomIntNumber拥有与之相同的价值randomUintNumber,那就去做吧

const int64_t randomIntNumber = randomUintNumber;
Run Code Online (Sandbox Code Playgroud)

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

const int64_t randomIntNumber = static_cast<int64_t>(randomUintNumber);
Run Code Online (Sandbox Code Playgroud)

如果randomUintNumber小于2 63,则转换的结果与输入的值相同.否则结果是实现定义的,但是我希望所有已知的实现int64_t都会定义它来做明显的事情:结果等同于输入模2 64.


如果你想randomIntNumber拥有相同的位模式randomUintNumber,那么你可以这样做:

int64_t tmp;
std::memcpy(&tmp, &randomUintNumber, sizeof(tmp));
const int64_t randomIntNumber = tmp;
Run Code Online (Sandbox Code Playgroud)

由于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;
Run Code Online (Sandbox Code Playgroud)

现在,我赞成在可能的情况下编写真正可移植的代码,但即便如此,我认为这接近于偏执狂.


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

const int64_t randomIntNumber = reinterpret_cast<int64_t&>(randomUintNumber);
Run Code Online (Sandbox Code Playgroud)

或等效地:

const int64_t randomIntNumber = *reinterpret_cast<int64_t*>(&randomUintNumber);
Run Code Online (Sandbox Code Playgroud)

这并不能保证能够正常工作,因为尽管它们存在int64_tuint64_t保证是有符号类型和相同大小的无符号类型,但它们实际上并不保证是标准整数类型的有符号和无符号版本.因此,无论此代码是否违反严格别名,它都是特定于实现的.违反严格别名的代码具有未定义的行为.以下并没有违反严格走样,并确定提供的位模式randomUintNumber是值的有效表示long long:

unsigned long long x = 0;
const long long y = reinterpret_cast<long long &>(x);
Run Code Online (Sandbox Code Playgroud)

因此,对实现地方int64_tuint64_t是类型定义为long longunsigned long long,然后我reinterpret_cast就可以了.就像实现定义的超出范围值到签名类型的转换一样,您可能希望实现的明智之处在于使它们成为对应的有符号/无符号类型.因此,static_cast与隐式转换一样,您希望它可以在任何合理的实现中工作,但实际上并没有保证.


she*_*heu 5

static_cast在这些情况下使用。我想语言设计者会以他们的全部智慧来决定认为它不足够“不安全”以致无法保证reinterpret_cast