因为这不是reinterpret_cast
的用途。使用reinterpret_cast
进行允许的所有转换都涉及指针或引用,唯一的例外是整数或枚举类型可以reinterpret_cast
成自身。这些都在标准中定义,[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
的超出范围值时具有相同的结果。但据我所知,这在标准中并不是保证的。
即使 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_t
和uint64_t
,它们保证是相同大小的有符号类型和无符号类型,但它们实际上并不保证是一个标准整数类型的有符号和无符号版本。因此,这段代码是否违反了严格别名规则取决于具体实现。违反严格别名规则的代码将产生未定义行为。以下代码不会违反严格别名规则,并且只要randomUintNumber
中的位模式是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
的实现中,我的reinterpret_cast
是可以的。就像将超出范围的值转换为有符号类型一样,您会期望实现的明智之举是将它们对应为有符号/无符号类型。因此,像static_cast
和隐式转换一样,您希望它在任何明智的实现中都能工作,但实际上并不保证。
memory_cast<>
,它使用memcpy
来正确地使用指定数据的位表示创建一个新对象,但我完全忘记了bit_cast
的存在。 - undefined