关于左移位,右移位运算符 [英] regarding left shift and right shift operator

查看:167
本文介绍了关于左移位,右移位运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 无效次(无符号短整型时间)
{
    小时=时间>> 11;
    分钟=((时间下;小于5)GT;大于10);
}

以输入时间 24446

的输出值

小时= 11

=分钟763

的预期值是

小时= 11

分钟= 59

什么样的​​内部处理这个code回事?

的二进制 24446 0101111101111110

时间>> 11 01011 这意味着 11

((时间和LT;< 5)>> 10) 111011 这意味着 59

还有什么在这里发生了什么?


解决方案

  

还有什么是怎么回事?


如果时间无符号短,还有

之间的一个重要区别

  =分钟((时间LT;< 5)>> 10);

 无符号短TEMP =时间<< 5;
分钟=温度>> 10;

在这两个前pressions,时间<< 5 的计算方法的 INT ,因为整数提升规则。 [注1和2。

在第一八佰伴pression,这个 INT 结果然后右移10.在第二个前pression,分配到无符号短温度缩小结果到,然后由10右移。

因此​​,在第二个前pression,高位被删除(通过强制转换为无符号短),而在第一八佰伴pression他们将不会被删除,如果 INT 短更宽

有与第一前pression另一个重要的警告。由于整数促销活动可能会改变一个无符号短 INT ,中间值可能签署,在这种情况下溢出如果左移足够大是可能的。 (在这种情况下,它不是)然后向右移位可能被应用到一个负数,则结果为实现定义;许多实现定义一个负数的右移位的数字符号扩展的行为。这也可能导致意外


注:


  1. 假设 INT 短更宽。如果 unsigned int类型无符号短的宽度都相同,没有转换会发生,你不会看到你的区别描述。在整型的提升,在与教派描述; C标准的6.3.1.1/2(使用C11草案):


      

    如果一个 INT 可以重新present原始类型的所有值(由宽度的限制,对于
      位字段),值转换为 INT ;否则,将其转换为符号
      INT
    。这些被称为整数促销。所有其他类型是由未变
      整型的提升。


    整数提升规则有效地使其无法直接与型比 INT 小做任何算术运算,尽管编译器可以使用假设规则中使用的分词运算codeS。在这种情况下,他们必须产生相同的结果将被制作成促进的数值已经;这很容易让未签名的加法和乘法,但棘手的转变。<​​/ p>


  2. 位移操作符是个例外算术运算的语义。对于大多数的算术运算,C标准要求,通常的算术转换在执行操作前被应用。通常的算术转换,除其他事项外,保证该两个操作数具有相同的类型,这也将是结果的类型。对于bitshifts,该标准只要求整数促销活动将在两个操作数执行,并且该结果将左操作数的类型。这是因为移位运算符是不是对称的。对于几乎所有的结构中,存在用于将不适合在一个无符号字符移位没有有效的右操作数,并且有明显不需要类型或左和右操作数的连带符号是相同的。

    在任何情况下,与所有算术运算符,整数优惠(至少)要被执行。所以你不会看到中间结果比 INT 窄。


void times(unsigned short int time)
{
    hours=time>>11;
    minutes=((time<<5)>>10);
}

Take the input time to be 24446

The output values are

hours = 11

minutes = 763

The expected values are

hours = 11

minutes = 59

What internal processing is going on in this code?

Binary of 24446 is 0101111101111110

Time>>11 gives 01011 which means 11.

((Time<<5)>>10) gives 111011 which means 59.

But what else is happening here?

解决方案

What else is going on here?

If time is unsigned short, there is an important difference between

minutes=((time<<5)>>10);

and

unsigned short temp = time << 5;
minutes = temp >> 10;

In both expressions, time << 5 is computed as an int, because of integer promotion rules. [Notes 1 and 2].

In the first expression, this int result is then right-shifted by 10. In the second expression, the assignment to unsigned short temp narrows the result to a short, which is then right-shifted by 10.

So in the second expression, high-order bits are removed (by the cast to unsigned short), while in the first expression they won't be removed if int is wider than short.

There is another important caveat with the first expression. Since the integer promotions might change an unsigned short into an int, the intermediate value might be signed, in which case overflow would be possible if the left shift were large enough. (In this case, it isn't.) The right shift might then be applied to a negative number, the result is "implementation-defined"; many implementations define the behaviour of right-shift of a negative number as sign-extending the number. This can also lead to surprises.


Notes:

  1. Assuming that int is wider than short. If unsigned int and unsigned short are the same width, no conversion will happen and you won't see the difference you describe. The "integer promotions" are described in §6.3.1.1/2 of the C standard (using the C11 draft):

    If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

    Integer promotion rules effectively make it impossible to do any arithmetic computation directly with a type smaller than int, although compilers may use the what-if rule to use sub-word opcodes. In that case, they have to produce the same result as would have been produced with the promoted values; that's easy for unsigned addition and multiplication, but trickier for shift.

  2. The bitshift operators are an exception to the semantics of arithmetic operations. For most arithmetic operations, the C standard requires that "the usual arithmetic conversions" be applied before performing the operation. The usual arithmetic conversions, among other things, guarantee that the two operands have the same type, which will also be the type of the result. For bitshifts, the standard only requires that integer promotions be performed on both operands, and that the result will have the type of the left operand. That's because the shift operators are not symmetric. For almost all architectures, there is no valid right operand for a shift which will not fit in an unsigned char, and there is obviously no need for the types or even the signedness of the left and right operands to be the same.

    In any event, as with all arithmetic operators, the integer promotions (at least) are going to be performed. So you will not see intermediate results narrower than an int.

这篇关于关于左移位,右移位运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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