c++ - 从 DWORD 中提取 lo 和 hi 字时为什么需要二进制移位?

标签 c++ c

首先对标题感到抱歉,我不想让它太长或令人困惑。如果有人可以帮助我使它更通用,因为这种情况可能适用于任何类型的位掩码操作。

[以下代码在 Windows 中运行(因此是小端)]

如果我有一个 DWORD(无符号长整型)和一个 WORD(无符号短整型),并且我想从双字中提取低位和高位字,为什么我不能这样做?

DWORD t = 0xAAAABBBB;
WORD loWord = t & 0x0000FFFF;
WORD hiWord = t & 0xFFFF0000;

对于 loWord,我得到正确的答案 0xBBBB,对于 hiWord,我只得到 0(请参阅最后的程序完整列表,以获取结果的打印输出)

我查了一下 Windows 宏是如何执行 HIWORD(_dw) 的,它所做的只是向右移动两个字节,然后像这样执行 AND 操作

DWORD t= 0xAAAABBBB; WORD hiWord = (t >> 16) & 0xFFFF;

但是我不明白的是,如果我们向右移动两个字节,为什么我们现在还需要执行 AND 运算?为什么甚至需要这种转变,为什么我的原始代码不能按预期工作?

为了说明为什么我对 AND 后的转变感到困惑,这就是我想象的转变工作方式:

0x AA AA BB BB  >> 16  -> 0x 00 00 AA AA 

这样做0x 00 00 AA AA & 0x00 00 FF FF在我看来毫无意义?我缺少什么?

更准确地说,宏首先将 DWORD 转换为指针,然后进行移位,如下所示(这是确切的宏)

#define HIWORD(_dw)     ((WORD)((((DWORD_PTR)(_dw)) >> 16) & 0xffff))

有人可以向我解释一下指针转换的目的吗?我尝试过使用和不使用,结果是一样的。

这是我在测试过程中使用的一个实际的短程序,用于完整说明该问题:

#include <iostream>
#include <Windows.h>


int main()
{
    DWORD t = 0xAAAABBBB;
    WORD loWord = t & 0x0000FFFF;
    WORD hiWordNoShift = t & 0xFFFF0000;
    WORD hiWordShift = (t >> 16) & 0xFFFF;

    cout << "t: " << std::hex << t << endl;
    cout << "hi (no shift): " << std::hex << hiWordNoShift << endl;
    cout << "hi (shift): " << std::hex << hiWordShift << endl;
    cout << "lo: " << std::hex << loWord << endl;



    system("pause");
    return 0;
}

结果是:

t: aaaabbbb
hi (no shift): 0
hi (shift): aaaa
lo: bbbb
Press any key to continue . . .

最佳答案

我认为是这样,因为HIWORD()应该是通用的并且应该采用CPU寄存器的大小。

在 64 位目标上,通用寄存器(如 RAX)是 64 位寄存器,并且 DWORD_PTR 的大小也是 64 位。 在 32 位目标上,通用寄存器(如 EAX)是 32 位寄存器,并且 DWORD_PTR 的大小也是 32 位。

这样编译器就可以生成更优化的代码。

关于c++ - 从 DWORD 中提取 lo 和 hi 字时为什么需要二进制移位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57835235/

相关文章:

C++:如何让不同的类函数操作我的类成员变量

c++ - 使用 Visual Studio 2013 进行过程 C++ 编程

无法使用来自另一个翻译单元的函数指针初始化静态结构?

c++ - vector 类错误

c++ - 给定字典和字母查找最长的单词

尽管未使用 Xcode,C 程序仍生成与 Xcode 相关的编译警告

Python:ctypes + C malloc 错误。 C内存问题还是Python/ctypes问题?

c - 输出中的额外整数

c - 遗憾的是,我的程序中名为 printf 的打印格式无法运行

c++ - 不理解 C++ STL 中 std::remove 的结果