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

前端之家收集整理的这篇文章主要介绍了在C 11中是左移(<<)负整数未定义的行为吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在C 11中左移一个负的int未定义行为?

相关的标准段落是5.8:

2/The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are zero-filled. If E1 has an unsigned type,the value of the
result is E1 × 2E2,reduced modulo one more than the maximum value
representable in the result type. Otherwise,if E1 has a signed type
and non-negative value,and E1×2E2 is representable in the result
type,then that is the resulting value; otherwise,the behavior is
undefined.

令我困惑的部分是:

Otherwise,if E1 has a signed type and non-negative value,and E1×2E2
is representable in the result type,then that is the resulting value;
otherwise,the behavior is undefined.

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

此外,前面的条款说:

1/The shift operators << and >> group left-to-right.
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

The operands shall be of integral or unscoped enumeration type and
integral promotions are performed.

The type of the result is that of the promoted left operand. The
behavior is undefined if the right operand is negative,or greater
than or equal to the length in bits of the promoted left operand.

这使得显式地使用一个操作数的负数为UB.如果是UB对另一个操作数使用负数,我希望在这里也明确.

所以,底线是:

-1 << 1

未定义行为?

@Angew provided对标准版的一个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的解释是正确的.

解决方法

是的,我会说这是未定义的.如果我们将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;

我会说出他们对右手操纵的明确原因,而不是左手操纵的原因是你所引用的paragrpah(右手操纵的情况)适用于左转和右转.

对于左手操纵,裁决不一致.左移一个负数是未定义的,右移它是实现定义的.

猜你在找的C&C++相关文章