在C ++ 11中左移(<<)一个负整数未定义的行为? [英] Is left-shifting (<<) a negative integer undefined behavior in C++11?

查看:201
本文介绍了在C ++ 11中左移(<<)一个负整数未定义的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否向左移动一个否定 int 在C ++ 11中未定义的行为?



这里是从5.8:


2 / E1的值< E2是E1左移E2位位置; vacated
位为零填充。如果E1具有无符号类型,
结果的值为E1×2E2,比在结果类型中可表示的最大值
减1。否则,如果E1具有签名类型
和非负值,并且E1×2E2可以在结果
类型中表示,那么这是结果值;


令我困惑的部分是:


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


这应该解释为意味着左移负数是UB?或者它只是意味着如果您的结果为负,并且结果不适合结果类型, 它是UB?



此外,前面的子句说:


1 / shift操作符<和>>从左到右。
shift-expression:
additive-expression
shift-expression<<添加表达式
shift-expression >> additive-expression



操作数应为整数或无范围的枚举类型,并执行
整数促销。



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


这使得明确的是,对于一个的操作数使用负数是UB。如果是UB对其他操作数使用负数,我希望在这里也清楚。



所以,底线是:

  -1<< 1 

未定义的行为?






@Angew 提供了对标准版的解释,简洁地表达了一个可能的(可能的)有效解释。其他人质疑这个问题是否真的关于语言行为是未定义的的适用性与我们的(StackOverflow的)使用短语未定义的行为。



@ Angew对Standardese的解释是:

  if(typeof(E1)== unsigned integral)
value = E1 * 2 ^ E2%blah blah;
else if(typeof(E1)== signed integral&& E1> = 0&&
else
value = undefined;

这个问题真正归结为这是正确的解释:

  value = E1 left-shift-by(E2)

switch(typeof(E1))
{
case unsigned积分:
value = E1 * 2 ^ E2%blah blah;
break;

表示签名整数:
if(E1> = 0)
{
if(representable(E1 * 2 ^ E2))
{
value = E1 * 2 ^ E2;
}
else
{
value = undefined;
}
}
break;
}



Sidenote,从psudocode的角度来看这一点在我看来,@ Agnew的解释是正确的。

解决方案

是的,我会说它是undefined。如果我们将standardese转换为伪代码:

  if(typeof(E1)== unsigned integral)
value = E1 * 2 ^ E2%blah blah;
else if(typeof(E1)== signed integral&& E1> = 0&&
else
value = undefined;

我会说明他们为什么要明确右手操作数,而不是左边的一个是你引用的paragrpah(右边的操作数的情况)适用于左右移位。



对于左边的操作数,裁决不同。左移负值是未定义的,右移是实现定义的。


Is left-shifting a negative int Undefined Behavior in C++11?

The relevant Standard passages here are from 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.

The part that confuses me is:

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.

Should this be interpreted to mean that left-shifting any negative number is UB? Or does it only mean if you LS a negative and the result doesn't fit in the result type, then it's UB?

Moreover, the preceding clause says:

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.

This makes it explicit that using a negative number for one of the operands is UB. If it were UB to use a negative for the other operand, I would expect that to be made clear here as well.

So, bottom line, is:

-1 << 1

Undefined Behavior?


@Angew provided a psudocode interpretation of the Standardese which succinctly expresses one possible (likely) valid interpretation. Others have questioned whether this question is really about the applicability of the language "behavior is undefined" versus our (StackOverflow's) use of the phrase "Undefined Behavior." This edit is to provide some more clarification on what I'm trying to ask.

@Angew's interpretation of the Standardese is:

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;

What this question really boils down to is this -- is the correct interpretation actually:

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, in looking at this in terms of psudocode makes it fairly clear in my mind that @Agnew's interpretation is the correct one.

解决方案

Yes, I would say it's undefined. If we translate the standardese to pseudo-code:

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;

I'd say the reason why they're explicit about the right-hand operand and not about the left-hand one is that the paragrpah you quote (the one with the right-hand operand case) applies to both left and right shifts.

For the left-hand operand, the ruling differs. Left-shifting a negative is undefined, right-shifting it is implementation-defined.

这篇关于在C ++ 11中左移(&lt;&lt;)一个负整数未定义的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆