为什么将值移动到超过其大小不会导致0?

时间:2017-01-10 09:51:05

标签: c++ arrays visual-c++

实际提炼的问题:

为什么不打印0?

#include "stdafx.h"
#include <iostream>
#include <string>

int _tmain(int argc, _TCHAR* argv[])
{
    unsigned char barray[] = {1,2,3,4,5,6,7,8,9};
    unsigned long weirdValue = barray[3] << 32;

    std::cout << weirdValue; // prints 4
    std::string bla;
    std::getline(std::cin, bla);
    return 0;
}

拆卸班次操作:

   10:  unsigned long weirdValue = barray[3] << 32;
00411424  movzx       eax,byte ptr [ebp-1Dh] 
00411428  shl         eax,20h 
0041142B  mov         dword ptr [ebp-2Ch],eax 

原始问题:

我在我们维护的一些旧代码中找到了以下代码段。它将字节数组转换为多个浮点值,并将浮点数添加到列表中。为什么它适用于大于4的字节数组?

unsigned long ulValue = 0;
for (USHORT usIndex = 0; usIndex < m_oData.usNumberOfBytes;  usIndex++)
{
    if (usIndex > 0 && (usIndex % 4) == 0)
    {
        float* pfValue = (float*)&ulValue;
        oValues.push_back(*pfValue);
        ulValue = 0;
    }

    ulValue += (m_oData.pabyDataBytes[usIndex] << (8*usIndex)); // Why does this work for usIndex > 3?? 
}

我会理解,如果&lt;&lt;是一个旋转操作员,而不是一个班次操作员。或者如果它是

ulValue += (m_oData.pabyDataBytes[usIndex] << (8*(usIndex%4)))

但像我发现的代码让我感到困惑。

使用VS 2005编译代码。 如果我在即时窗口中尝试原始片段,它虽然不起作用。

我知道如何正确地做到这一点,我只是想知道为什么代码,尤其是移位操作的工作原理。

编辑:班次操作的反汇编是:

13D61D0A  shl         ecx,3   // multiply uIndex by 8
13D61D0D  shl         eax,cl  // shift to left, does nothing for multiples of 32
13D61D0F  add         eax,dword ptr [ulValue] 
13D61D15  mov         dword ptr [ulValue],eax 

所以反汇编很好。

1 个答案:

答案 0 :(得分:1)

移位计数被屏蔽为5位,这将范围限制为0-31。

因此,32的偏移与零的偏移相同。

http://x86.renejeschke.de/html/file_module_x86_id_285.html