在C ++ 11中左移(<<)是否为负整数未定义行为?

时间:2013-10-25 15:31:15

标签: c++ c++11 language-lawyer

在C ++ 11中左移{负1 int未定义行为?

此处的相关标准段落来自5.8:

  

2 / E1的值<&lt; E2是E1左移E2位位置;腾空   位是零填充的。如果E1具有无符号类型,则为   结果是E1×2E2,比最大值减少一个模数   在结果类型中可表示。否则,如果E1具有签名类型   和非负值,E1×2E2在结果中可表示   type,那就是结果值;否则,行为是   未定义。

困扰我的部分是:

  

否则,如果E1具有有符号类型和非负值,则E1×2E2   可以在结果类型中表示,那么这就是结果值;   否则,行为未定义。

这是否应该被解释为左移任何负数是UB?或者它只是意味着如果你LS为负数且结果不适合结果类型,那么它是UB?

此外,前面的条款说:

  

1 /移位运算符&lt;&lt;和&gt;&gt;从左到右组。       移位表达:           添加剂的表达           shift-expression&lt;&lt;添加剂的表达           shift-expression&gt;&gt;添加剂的表达

     

操作数应为整数或无范围的枚举类型   整体促销活动。

     

结果的类型是提升的左操作数的类型。该   如果右操作数为负数或更大,则行为未定义   大于或等于提升的左操作数的位数。

这明确表示对操作数的一个使用负数是UB。如果UB对另一个操作数使用负数,我希望在这里也可以明确。

所以,底线是:

-1 << 1

未定义的行为?


@Angew provided对替补的一种伪代码解释,它简洁地表达了一种可能的(可能的)有效解释。其他人质疑这个问题是否真的与“行为未定义”的语言的适用性相比,而我们(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;
}

旁注,从psudocode的角度来看这个问题让我很清楚@Agnew的解释是正确的。

3 个答案:

答案 0 :(得分:8)

是的,我会说这是未定义的。如果我们将标准转换为伪代码:

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;

我会说他们明确右手操作数而不是左手操作数的原因是你引用的paragrpah(右手操作数的情况)适用于左边和右边操作数。正确的转变。

对于左手操作数,裁决有所不同。左移一个负数是未定义的,右移它是实现定义的。

答案 1 :(得分:5)

  

这应该被解释为左移任何负数是UB吗?

是的,当给出任何负数时,行为未定义。只有满足以下两个条件时才会定义行为:

  • 该数字为非负数
  • E1×2 E2 在结果类型
  • 中可表示

这实际上是“如果E1具有有符号类型和非负值,并且E1×2 E2 在结果类型中是可表示的,那么这就是结果值;否则,行为是未定义,“说:

if X and Y
  then Z
else U

答案 2 :(得分:1)

根据问题回答:

问题确实是:

  

我们可以将术语“行为未定义”等同于术语“未定义行为”。

目前的措辞意味着“未定义的行为”。

关于情况的个人评论

但我不相信这是作者的意图 如果这是作者的意图,那么我们应该有一个说明解释原因。但是我更倾向于认为作者意味着该操作的结果是未定义的,因为标准没有明确定义负数的表示。如果没有为负数明确定义负数的表示,那么移动这些位将导致未定义的值。

无论哪种方式,措辞(或解释)都需要加强/扩展,以使其不那么模糊。