左移是负面的 int
C ++ 11中未定义的行为?
这里的相关标准段落来自5.8:
2 / E1 << E2的值是E1左移E2位的位置;腾空 位是零填充的。如果E1具有无符号类型,则该值为 结果是E1×2E2,比最大值减少一个模数 在结果类型中可表示。否则,如果E1具有签名类型 和非负值,E1×2E2在结果中可表示 type,那就是结果值;否则,行为是 未定义。
令我困惑的部分是:
否则,如果E1具有有符号类型和非负值,则E1×2E2 可以在结果类型中表示,那么这就是结果值; 否则,行为未定义。
这应该被解释为意味着左移 任何 负数是UB?或者它只是意味着什么 如果 你LS为负数,结果不适合结果类型, 然后 这是UB?
而且,前一条款说:
1 /移位运算符<<和>>组从左到右。 移位表达: 添加剂的表达 shift-expression << additive-expression shift-expression >> additive-expression
操作数应为整数或无范围的枚举类型 进行整体促销。
结果的类型是提升的左操作数的类型。该 如果右操作数为负数或更大,则行为未定义 大于或等于提升左操作数的位长。
这使得明确使用负数 一 操作数是UB。如果UB对另一个操作数使用负数,我希望在这里也要明确。
所以,底线是:
-1 << 1
未定义的行为?
@Angew 提供 对标准的一种psudocode解释简洁地表达了一种可能的(可能的)有效解释。其他人质疑这个问题是否真的与“行为未定义”的语言相对于我们(StackOverflow)使用“未定义行为”这一短语的适用性。这个编辑是为了提供一些我想要问的更多说明。
@Angew对Standardese的解释是:
if (typeof(E1) == unsigned integral)
value = E1 * 2^E2 % blah blah;
else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2))
value = E1 * 2^E2;
else
value = undefined;
这个问题真正归结为这个 - 实际上是正确的解释:
value = E1 left-shift-by (E2)
switch (typeof(E1))
{
case unsigned integral :
value = E1 * 2^E2 % blah blah;
break;
case signed integral :
if (E1 >= 0)
{
if (representable(E1 * 2^E2))
{
value = E1 * 2^E2;
}
else
{
value = undefined;
}
}
break;
}
?
Sidenote,从psudocode的角度来看这个问题让我很清楚@Agnew的解释是正确的。