zoukankan      html  css  js  c++  java
  • C/C++移位运算符出界后的结果是不可预期的

    以前看到C++标准上说,移位运算符(<<、>>)出界时的行为并不确定:

    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.

    我当时也没有深究过这个问题。前几天有个网友来信问起这件事,我才发现,这和Intel CPU的移位运算有关。下面是那位网友的来信以及我的回复:


    您好!运算符<<作为位操作中的高效的操作,但我遇到一个问题:下面在VC环境下发现一个很不明白的地方,下面标注。

    #include <stdio.h>
    void main()
    {
       unsigned int i,j;
       i=35;

       //为什么下面两个左移操作结果不一样?
       j=1<<i;  // j为8
       j=1<<35; // j为0
    }

    不知是哪里没有理解对。


    原因是这样的:i=35;j=1<<i;这两句在VC没有做优化的情况下,将被编译成下面的机器指令:

    mov dword ptr [i],23h
    mov eax,1
    mov ecx,dword ptr [i]
    shl eax,cl
    mov dword ptr [j],eax

    在shl一句中,eax=1,cl=35。而Intel CPU执行shl指令时,会先将cl与31进行and操作,以限制左移的次数小于等于31。因为35 & 31 = 3,所以这样的指令相当于将1左移3位,结果是8。

    而j=1<<35;一句是常数运算,VC即使不做优化,编译器也会直接计算1<<35的结果。VC编译器发现35大于31时,就会直接将结果设置为0。这行代码编译产生的机器指令是:

    mov dword ptr [j],0

    对上面这两种情况,如果把VC编译器的优化开关打开(比如编译成Release版本),编译器都会直接将结果设置为0。

    所以,在C/C++语言中,移位操作不要超过界限,否则,结果是不可预期的。

    下面是Intel文档中关于shl指令限制移位次数的说明:

    The destination operand can be a register or a memory location. The count operand can be an immediate value or register CL. The count is masked to 5 bits, which limits the count range to 0 to 31. A special opcode encoding is provided for a count of 1.

  • 相关阅读:
    Microsoft EBooks
    JavaScript 数据访问(通译自High Performance Javascript 第二章) [转]
    time random sys os模块
    configparser logging collections 模块
    序列化模块和hashlib模块
    内置方法
    面向对象进阶
    property classmethod staticmethod的用法
    归一化设计,抽象类和接口类,接口隔离操作
    面向对象的三大属性
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157278.html
Copyright © 2011-2022 走看看