C++ 为什么将值移到大于其大小的位置不会导致0?

C++ 为什么将值移到大于其大小的位置不会导致0?,c++,arrays,visual-c++,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 <&

实际精炼问题:

为什么不打印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;
}

因此,反汇编很好。

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

因此,32的移位与零的移位相同


代码实际上是不正确的。除非通过
char
数组显式执行,否则无法执行此操作。使用中间
ulValue
会将代码转化为非法行为,在技术上是未定义的行为。而且,由于
long
float
之间的endianness和可能的大小差异,它不会在所有平台上都工作。您对它的实际工作有多大把握?在现实世界中运行时,USNBytes的数量是否会超过3?目前,该代码无法用于usIndex>3I,我想知道它为什么在这里工作。我知道有更好的解决方案,我只是想知道为什么这一方法在过去的十年里奏效。是的,我有一个例子,usNumberOfBytes是28,一种可能的工作方式,正确的方法可能是这样做,例如
float fValue=*(float*)&m_oData.pabyDataBytes[usIndex]
,然后用
sizeof(float)
增加
usIndex
。那么你真正想问的是移位操作,以及它为什么“有效”?也许您可以稍微澄清一下,删除不相关的代码?最好创建一个?实际上,它不应该起作用。如果
sizeof(unsigned long)==4
,则当
usIndex>3
时,它将移位到许多位,并导致未定义的行为。
   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 
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?? 
}
ulValue += (m_oData.pabyDataBytes[usIndex] << (8*(usIndex%4)))
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