C ++ 20是否为“溢出”的有符号整数很好地定义了左移?

Dan*_*ica 11 c++ bit-shift language-lawyer c++20

在当前的C ++标准草案中,左移位运算符的定义如下[expr.shift]

的值E1 << E2唯一的值一致来E1×2^E22^N,其中N是结果的类型的宽度。

考虑int E1 = 2^31-1 = 2'147'483'647E2 = 1并且int具有32位。再有就是数的无限数量一致,以 E1×2^E2 = 4'294'967'2942^N = 2^32,即,所有的数字4'294'967'294 + k×2^32,其中k的任意整数。示例是4'294'967'294k=0)或-2k=-1)。

我不明白这些数字中的唯一值表示标准的含义。这是否意味着可以由结果数据类型表示的唯一值?然后,我假设结果定义为-2。这种解释正确吗?

在C ++ 20之前,定义是不同的,这种情况将导致未定义的行为。我想这个变化与负号整数的强制性2's补码表示有关。

实际上,现在不再E1需要非负数。因此,似乎将-1 << 1其定义为-2。那也对吗?

bol*_*lov 6

它是否表示可以由结果数据类型表示的唯一值

是。与E1×2^E2模数相等的一组数字2^N是无限的,但是在任意大小的间隔中2^N只有一个值,因此在width的整数类型中只有一个可表示的值N

如果查看“ p0907R1有符号整数是二进制补码”提案,我们会发现一个带有“唯一表示形式”的类似短语,这使得这一点更加清楚:

从有符号到无符号的转换始终是明确定义的:结果是目标类型的唯一值,该唯一值与源整数2 N为模。

然后,我假设结果定义为-2。这种解释正确吗?

在x64上,等效的asm指令为shlx(逻辑左移)

我想这个变化与负号整数的强制性2补码表示有关。

正确。与无符号类型一样,现在它们也用数学方式表示等效类(嗯,我不清楚这是正确的多少,因为看起来他们仍然想让某些UB实例保持溢出状态)。

  • 重要术语“ congruent”一词是定义明确的数学术语:https://en.wikipedia.org/wiki/Modular_arithmetic (4认同)