请考虑以下代码:
int32_t x = -2;
cout << uint64_t(x) << endl;
第二行中的强制转换基本上包含两个原子步骤。位宽从32位增加到64位,解释从有符号变为无符号。如果用g ++编译并执行,则得到18446744073709551614.这表明首先处理位宽的增加(作为带符号的扩展),然后改变有符号/无符号解释,即上面的代码等同于写:< / p>
int32_t x = -2;
cout << uint64_t(int64_t(x)) << endl;
让我感到困惑的是,人们也可以先将x解释为无符号32位位向量,然后将其零扩展为64位,即
int32_t x = -2;
cout << uint64_t(uint32_t(x)) << endl;
这将产生4294967294.有人请确认标准是否需要g ++的行为并且不是实现定义的?如果你能引用我的标准实际上涉及到手头的问题,我会非常兴奋。我试图这样做但是痛苦地失败了。
提前致谢!
答案 0 :(得分:2)
您正在寻找标准版4.7。特别是,第2段说:
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n 其中 n 是用于表示无符号类型的位数。)
在给定的例子中,我们有18446744073709551614 = -2 mod 2 64 。
答案 1 :(得分:0)
正如@aschepler所说,标准4.7§2(积分转换)确保结果将是与源一致的最小无符号整数 整数(模2n,其中n是用于表示无符号类型的位数)
所以在你的情况下,它将是0xFFFFFFFFFFFFFFFE == 18446744073709551614
但这是标准规定的一步转换(编译器实际做的是超出范围)
如果您想首先将无符号转换为uint32_t,然后转换为uint64_t,则必须指定2次转化:static_cast<uint64_t>(static_cast<uint32_t>(-2))
按照4.7§2,首先给出0xFFFFFFFE = 4294967294,但由于这个数字已经是有效的uint64_t,所以它在第二次转换时没有改变。
您所观察到的内容是标准所要求的,并且可以在任何符合标准的编译器上进行观察(已提供uint32_t
和uint64_t
,因为此部分不是必需的。 。)