对移位行为的怀疑
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 中,这是否意味着 positivesigned
整数的右移是明确定义的?如果值不可表示,我想 positive 'signed` 整数上的左移不是。
我说的是最新发布的标准 C++17(问题被标记为)。我不知道最新的草稿是否有所改变。
"在 C++17 中,这是否意味着正符号整数的右移是明确定义的?"是的。 “如果值不可表示,我认为正‘有符号’整数上的左移不是。”如果结果在未签名版本中不可表示,则它仅是 UB。因此,转移到符号位是好的(实现定义的),但转移更多则不是。但这些规则不再重要,因为下一个草案简化了它们,因为它需要二进制补码。以上是关于对移位行为的怀疑的主要内容,如果未能解决你的问题,请参考以下文章