在 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->data[i]
是一个 32 位值(或更小)。顺便说一句,您不应该将解决方案编辑到问题中,而是可以发布答案。 (尽管回答您自己的问题可能有最低代表要求,IDK)。
请不要发布有问题的答案。你可以answer你自己的问题。
@MartinZhai 根据该链接需要 15 个代表,所以我猜在这种情况下 OP 不走运
如果调试器说m->data[i]
是0xC0
那么它可能是一个字节(8 位数量) - 根据标准提升规则提升为int
。 int
在你的编译器上是 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->data[i] == 0xC0
和shift == 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位的时候, 出现的问题;