Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我能';我不明白为什么HIWORD宏使用&;0xFFFF面具?_C_Winapi - Fatal编程技术网

C 我能';我不明白为什么HIWORD宏使用&;0xFFFF面具?

C 我能';我不明白为什么HIWORD宏使用&;0xFFFF面具?,c,winapi,C,Winapi,摘自查尔斯·佩佐尔德的书: 几乎在每个Windows程序中都会看到这样的代码。洛沃德 和HIWORD是在Windows头文件中定义的宏 WINDEF.H。如果你好奇的话,这些宏的定义看起来 像这样 #define LOWORD(l) ((WORD)(l)) #define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) 这两个宏返回字值,即16−位无符号 我只会在HIWORD定义中使用shift运算符。 像这样: #defi

摘自查尔斯·佩佐尔德的书:

几乎在每个Windows程序中都会看到这样的代码。洛沃德 和HIWORD是在Windows头文件中定义的宏
WINDEF.H
。如果你好奇的话,这些宏的定义看起来 像这样

#define LOWORD(l) ((WORD)(l))
#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) 
这两个宏返回字值,即16−位无符号

我只会在HIWORD定义中使用shift运算符。 像这样:

#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16))
他为什么要掩盖这个价值观

有人能给我解释一下吗

编辑:

我怎么了

& 0xFFFF
它确保前16位将被忽略

0x12345678 & 0x0000FFFF == 0x00005678

移位不能确保留下零(尝试移位-1),因此它们使用按位and来确保这一点。

我想你的观点是,因为
WORD
保证为16位,那么
(WORD)(x>>16)
无论如何只能是16位,因此掩码是无用的

或者,可能是因为
DWORD
保证是32位无符号的,那么
(x>>16)
保证除了较低的16位之外,不设置任何位

在早期,计划将
WORD
与系统的CPU字大小相匹配(即
int
)。然而,事实证明,当Win32问世时,由于编写了太多不可移植的代码,它会破坏太多东西,无法生成32位和64位的
WORD
DWORD

也许这个宏从未更新过。但是,我们可以肯定地说,
&0xFFFF
不可能导致问题,因此没有理由删除它。(不要修理没坏的东西!)


也许保留它甚至是一个好主意,以防万一
WORD
不断增加。

我猜一些旧编译器会抱怨(在编译过程中发出警告)如果不使用&0xFFFF,可能会被截断,尽管正如本线程其他部分所指出的,它不是必需的。

在32位寄存器中,hiword位于左侧(16)位, Loword位于右侧(16)位 LOWORD(l)(单词)(l)和0XFFFF 这意味着0XFFFF掩码返回 寄存器的右侧。 HIWORD(l)(WORD)(l)>>16)和0XFFFF 这会将32位值向右移动16位 或者比特。所以我们现在在右边有一个词 0XFFFF掩码是AND,这给了我们HIWORD
希望这个答案足够。

也许这是因为整数转换规则没有标准化。这本书写在1998年(编程Windows第5版),我有2002年的版本。这本书是我们学习Windows的那本书,最初出版于1988年。在任何情况下,Petzold都不会写入Windows头文件。这些宏可以追溯到时间的黎明。我不知道WORD和DWORD的实际定义,但想想当
l
超过32位时会发生什么。如果不屏蔽结果,则值可能大于
2^16-1
。顺便说一句,作为对您上述评论的回应:0xFFFF将保留右移16位的位,并将之前的所有位置零。您得到了错误的strax,它不会将您刚刚推对的位置零。它将把从左边推入的新数字归零。它将保留刚才按下的16位。头文件的最新版本将转换为
DWORD\u PTR
,FWIW@DavidHeffernan他们到底说了什么?
#定义LOWORD(l)((WORD)((DWORD_PTR)(l))和0xffff))#定义HIWORD(l)((WORD)((DWORD_PTR)(l))>>16和0xffff))
@DavidHeffernan我很难理解他们为什么不坚持原版,这似乎没有什么不同好吧,
&0xffff
也可以删除,假设符合标准的无符号整数转换和支持的整数类型大小。转换为
也将确保忽略前16位。所以有人想知道为什么需要做两次。你知道吗?不,那会让你的答案更糟。这里的所有类型都是未签名的。你知道无符号转换的规则吗?对不起,我想我当时回答得有点太快了。我看不出有任何其他原因需要这样做两次,除非您希望与外来编译器兼容
& 0xFFFF
0x12345678 & 0x0000FFFF == 0x00005678