我有这样的价值:
int64_t s_val = SOME_SIGNED_VALUE;
Run Code Online (Sandbox Code Playgroud)
我怎么能得到一个
uint64_t u_val
Run Code Online (Sandbox Code Playgroud)
具有完全相同的位模式s_val
,但被视为无符号?
这可能非常简单,但在查看Stackoverflow和其他地方后,我没有找到答案.
Kir*_*sky 34
int64_t s_val = SOME_SIGNED_VALUE;
uint64_t u_val = static_cast<uint64_t>(s_val);
Run Code Online (Sandbox Code Playgroud)
C++标准4.7/2指出:
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n,其中n是用于表示无符号类型的位数).[注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断).]
另一方面,标准说"由reinterpret_cast
执行定义执行的映射.[注意:它可能会或可能不会产生与原始值不同的表示."(5.2.10/3).所以,我建议使用static_cast
.
请注意,您根本不需要演员表.对于所有关于演员阵容是否会因为负面表现而变得无聊的争论,有一件事已经丢失 - 演员阵容完全没必要.
由于C/C++将进行转换(以及如何定义转换),因此:
int64_t s_val = SOME_SIGNED_VALUE;
uint64_t u_val = s_val;
Run Code Online (Sandbox Code Playgroud)
完全等同于:
int64_t s_val = SOME_SIGNED_VALUE;
uint64_t u_val = static_cast<uint64_t>(s_val);
Run Code Online (Sandbox Code Playgroud)
也就是说,你可能仍然想要演员,因为它表明意图.但是,我听说它认为你不应该使用不必要的强制转换,因为它可能会在你可能需要警告的情况下使编译器静音.
选择你的毒药.
我同意static_cast在这种情况下是合适的,但是没有人提到过一个非常类似的情况,其中static_cast不会像预期的那样保留位.
char x = -1; // 255
unsigned int x2 = static_cast<unsigned int>(x); // 4294967295
unsigned int x3 = static_cast<unsigned int>(static_cast<unsigned char>(x)); // 255
Run Code Online (Sandbox Code Playgroud)
从小符号值转换为大的无符号值时,请注意符号扩展.可能其他组合也很脆弱 - 我没有想到它一直都是如此.
想要分享这个 C++14 现代通用解决方案。原来是在这里演示的。
template<class T>
auto as_unsigned(T t)
{
return std::make_unsigned_t<T>(t);
}
Run Code Online (Sandbox Code Playgroud)
可以按如下方式使用:
auto sx = int32_t{ 55 };
auto ux = as_unsigned(sx);
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看它的实际效果。
逻辑位模式(值表示的位),即二进制数字的值只有在原始有符号值为非负数时才能保留,因为负值不能用无符号整数变量表示.您需要做的就是将已签名的值分配给未签名的整数对象,然后就完成了
uint64_t u_val = s_val;
Run Code Online (Sandbox Code Playgroud)
显式强制转换不是必需的,但可能用于抑制编译器警告.
至于物理位模式(即你在原始内存中看到的,对象表示的位),你根本无法以这种方式"转换"它.C++语言没有为您提供任何可以保证保留物理位模式的转换方法.您所能做的就是将签名对象占用的内存重新解释为相同大小的无符号对象
STATIC_ASSERT(sizeof(int64_t) == sizeof(uint64_t));
uint64_t u_val = reinterpret_cast<uint64_t&>(s_val);
Run Code Online (Sandbox Code Playgroud)
同样,这不是转换,而是内存重新解释.这不能保证工作,这通常是非法的.