对移位行为的怀疑

Posted

技术标签:

【中文标题】对移位行为的怀疑【英文标题】:Doubts on bit-shifting behavior 【发布时间】:2019-05-25 09:16:58 【问题描述】:

我想澄清一些关于位移的疑虑:

    使用unsigned int

    unsigned int i = 500;i << 24;

    据我所知,这会导致unsigned int 溢出,这完全可以吗?

C++17 (8.5.7/2) - E1

    signed int 上使用右移完全没问题,只要我的移位小于“32 位”,因为“int”在我的平台上是 32 位。

    int i = 500;i >> 31;

这是溢出吗?

C++17 (8.5.7/3) E1 >> E2 的值是 E1 右移 E2 位的位置。如果 E1 有 一个无符号类型,或者如果 E1 有一个有符号类型和一个非负值, 结果的值是商的整数部分 E1/2^E2。

【问题讨论】:

没有unsigned 溢出。当 unsigned 值发生溢出时,该数字会以类型 + 1 的最大值为模减少。存在 signed 溢出。 【参考方案1】:

    这样可以吗?

    是的。 i 将变为 4093640704,十六进制为 0xf4000000

    这是溢出吗?

    没有。这是一个右移(类似除法的操作),所以i 会变为零。

请注意,关于班次的规则很可能会发生变化。目前,有几种情况是未定义的行为或定义的实现。由于下一个标准将需要二进制补码算法,因此有关移位的规则将放宽:唯一未定义的行为将是,如果移位量大于或等于类型的宽度。以下是当前的规则草案:link。

【讨论】:

如果你左移一个负值,或者如果一个正符号值的左移溢出,它也是未定义的。 @interjay:你的意思是,在当前的标准草案中? (我说的是目前的草稿) 在 C++17 中,这是否意味着 positive signed 整数的右移是明确定义的?如果值不可表示,我想 positive 'signed` 整数上的左移不是。 我说的是最新发布的标准 C++17(问题被标记为)。我不知道最新的草稿是否有所改变。 "在 C++17 中,这是否意味着正符号整数的右移是明确定义的?"是的。 “如果值不可表示,我认为正‘有符号’整数上的左移不是。”如果结果在未签名版本中不可表示,则它仅是 UB。因此,转移到符号位是好的(实现定义的),但转移更多则不是。但这些规则不再重要,因为下一个草案简化了它们,因为它需要二进制补码。

以上是关于对移位行为的怀疑的主要内容,如果未能解决你的问题,请参考以下文章

对 C++ 指针的怀疑

对 c++ 类的怀疑

对身份验证技术的怀疑 - 护照

对单元测试 DAO 的怀疑

对 t.test 结果的怀疑

对 Web 组件项目结构和导入的怀疑