在 VS 中的 UINT64 上左移 (64 > shift > 32) 位仅移动 32 位

Posted

技术标签:

【中文标题】在 VS 中的 UINT64 上左移 (64 > shift > 32) 位仅移动 32 位【英文标题】:Left-shift by (64 > shift > 32) bits on UINT64 in VS shifts only 32 bits 【发布时间】:2017-04-05 03:11:37 【问题描述】:

我正在为 Win64 上的 32 位程序编写 DLL 插件,在 Visual Studio 2015 中编译为 Win32/Debug。我需要将 unsigned char(上游定义)左移 56 位到 UINT64 中,以便 0xFF应该变成 0xFF000000000000。

实际发生的情况是,对于任何大于 32 的移位值,结果是 (shift - 32) 位的移位,我的目标 UINT64 的高 32 位变为全 1,因此:

int     NmeaPgn::sf_get_bytes(TCanMessage *m, UINT8 start_byte, UINT8 bytes)

    UINT64 r = 0; /* Could need to fetch up to 8 bytes, as in 60928 */
    INT8 i;

    for (i = start_byte + bytes - 1; i >= start_byte; --i)
    
        r |= (m->data[i] << 8 * (i - start_byte));
    
...

使用 VS 调试器,我看到:

m->data[i] == 0xC0
i == 0x7
start_byte == 0
bytes == 8 (so that shift == 8 * (7 - 0) == 56)

then:
r == 0xFFFFFFFFc0000000

我已阅读:

https://msdn.microsoft.com/en-us/library/336xbhcz.aspx

C++ bitwise left shift by 32

Left shift an integer by 32 bits

我能看到的最接近答案的是 Andrey Nasonov 对后者的回答 (https://***.com/a/33058550/7817631),但我使用的是 64 位机器(Core i5 上的 Win7-64),所以我不希望这是直接相关。

【问题讨论】:

可能m-&gt;data[i] 是一个 32 位值(或更小)。顺便说一句,您不应该将解决方案编辑到问题中,而是可以发布答案。 (尽管回答您自己的问题可能有最低代表要求,IDK)。 请不要发布有问题的答案。你可以answer你自己的问题。 @MartinZhai 根据该链接需要 15 个代表,所以我猜在这种情况下 OP 不走运 如果调试器说m-&gt;data[i]0xC0 那么它可能是一个字节(8 位数量) - 根据标准提升规则提升为intint 在你的编译器上是 32 位......你得到一个 32 位移位。事实上,你可以合法地得到从time travel 到程序终止的任何结果,因为在 C++ 中未定义大于被移位整数值大小的移位结果 - here's an answer to that effect。 顺便说一句,如果您将示例缩减为 minimal reproducible example - 一种非常有用的发现技术,您本可以自己解决这个问题。 【参考方案1】:

(由于 TomGreen 还不能回答他自己的问题,所以这是他的答案)

我必须将我的 unsigned char 显式转换为 UINT64,如下所示:

r |= ((UINT64)m->data[i] << 8 * (i - start_byte));

这会产生预期值(0xC000000000),其中m-&gt;data[i] == 0xC0shift == 56

【讨论】:

以上是关于在 VS 中的 UINT64 上左移 (64 > shift > 32) 位仅移动 32 位的主要内容,如果未能解决你的问题,请参考以下文章

OSX vs Linux:如何处理 unsigned long 和 uint64_t?

VS 编译MFC 32位转 64 位报错 ON_WM_TIMER()在编译器从32位转换为64位的时候, 出现的问题;

VS 编译MFC 32位转 64 位报错 ON_WM_TIMER()在编译器从32位转换为64位的时候, 出现的问题;

VS 编译MFC 32位转 64 位报错 ON_WM_TIMER()在编译器从32位转换为64位的时候, 出现的问题;

为啥 uint32_t 与 uint64_t 速度不同?

Go 语言中的通用类型(int / uint)相对于特定类型(int64 / uint64)有啥优势?