As I understand right shift does sign extension, thus signed negative numbers leave 1s, signed positive and unsigned numbers leave 0s in the upper bits.
Some test code:
Code:
#include <stdio.h>
typedef unsigned long DWORD;
typedef unsigned short WORD;
#define LOWORD(a) ((WORD)(a))
#define HIWORD(a) ((WORD)(((DWORD)(a) >> 16) & 0xFFFF))
int main()
{
int a=-1; // signed numbers are stored in two's complement, so this equals 0xFFFFFFFF
printf("a >> 16 == %X\n",a >> 16); // FFFFFFFF
printf("(DWORD)(a) >> 16 == %X\n",(DWORD)(a) >> 16); //FFFF
printf("\n");
a=0xABCD1234;
//upper bits are sign extended -> int a : signed
printf("a >> 16 == %X\n",a >> 16); // FFFFABCD
//no sign extension -> (DWORD) is an unsigned cast
printf("(DWORD)(a) >> 16 == %X\n",(DWORD)(a) >> 16); //ABCD
return 0;
}
For me it seems that there is still no need for a mask, because there is an unsigned cast in the macro definition: (DWORD)(a). So, why the need for the mask '& 0xFFFF' when we already have an unsigned cast?