简体   繁体   中英

Why does shifting a value further than its size not result in 0?

Actual refined question:

Why does this not print 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;
}

The disassembly of the shift operation:

   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 

Original question:

I found the following snippet in some old code we maintain. It converts a byte array to multiple float values and adds the floats to a list. Why does it work for byte arrays greater than 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?? 
}

I would understand that this works if << was a rotate operator, not a shift operator. Or if it was

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

But the code like i found it just confuses me.

The code is compiled using VS 2005. If i try the original snippet in the immediate window, it doesn't work though.

I know how to do this properly, i just want to know why the code and especially the shift operation works as it is.

Edit: The disassembly for the shift operation is:

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 

So the disassembly is fine.

The shift count is masked to 5 bits, which limits the range to 0-31.

A shift of 32 therefore is same as a shift of zero.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM