繁体   English   中英

int32_t 到 uint64_t 转换的顺序

[英]Order of int32_t to uint64_t casting

C++标准是否保证integer转换既加宽又去掉符号是符号扩展还是零扩展?

快速测试:

int32_t s = -1;
uint64_t u = s;

在 Xcode 下产生 0xFFFFFFFFFFFFFFFF,但这是首先定义的行为吗?

当你这样做

uint64_t u = s;

[dcl.init]/17.9适用,其中规定:

正在初始化的 object 的初始值是初始化表达式的(可能转换的)值。 如有必要,将使用标准转换序列 ([conv]) 将初始化表达式转换为目标类型的 cv 非限定版本; 不考虑用户定义的转换。

如果我们查看[conv] ,在积分转换下,我们有

否则,结果是与源 integer 模 2 N一致的目标类型的唯一值,其中 N 是目标类型的宽度。

所以你保证会发生的是 -1 成为可能表示的最大数字,-2 比它少一,-3 比 -2 少一,依此类推,基本上它“环绕”。


实际上,

unsigned_type some_name = -1;

是为该无符号 integer 类型创建具有最大值的变量的规范方法。

您可以在其他答案中找到标准措辞。

但是为了帮助您形成一个直观的心理 model 扩大转换,将这些视为一个两步过程会很有帮助:

  1. 值的符号扩展或零扩展。 如果值是有符号类型,则使用符号扩展。 这里int32_t符号扩展为int64_t 在 x86 上,类型的有符号性决定了使用的是MOVSX还是MOVZX指令。
  2. 将扩展值转换为目标类型(更改符号)。 这里int64_t被转换为uint64_t 它涉及 0 条汇编指令,因为寄存器是无类型的,编译器只是将包含int32_t符号扩展结果的寄存器视为uint64_t

请注意,该标准没有指定这些步骤,它只是指定了所需的结果。

积分转换部分:

[conv.integral/3]:否则,结果是与源 integer 模2 N一致的目标类型的唯一值,其中N是目标类型的宽度。

换句话说,环绕“最后发生”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM