# Thread: HIWORD and LOWORD macros

1. ## HIWORD and LOWORD macros

I have seen the HIWORD and LOWORD in some winapi header file. As their name suggests they select the higher or lower WORD (16bit) from a DWORD(32bit). Whats the function of the '& 0xFFFF' in the definition of the HIWORD macro? I know what it does, but for me, it seems pointless. The right shift leaves 0s in the higher 16bits anyway, so whats the point in masking them out?

Simple test program:
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()
{
DWORD d=0xABCD1234;

printf("Original value:\n");
printf("       d  == %X\n",d);

printf("\nMacros:\n");
printf("LOWORD(d) == %X\n", LOWORD(d));
printf("HIWORD(d) == %X\n", HIWORD(d));

printf("\nSimple hiword:\n");
printf("  d >> 16 == %X\n", d >> 16);

return 0;
}```

2. Because the right shift may or may not leave zeroes. Try shifting -1 >> 16 and see what happens.

3. ## ...

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            == &#37;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?

4. I didn't notice the cast. So someone was probably just being paranoid.

5. Its good to know I don't miss anything there. Thanks for the help!

6. Or they wanted to be sure that they could stuff that into a WORD without warnings.

7. Also, if you use the and at the end of such an operation, most optimizing compilers will "know" if it actually needs to perform the and operation or not - and thus it's not actually causing a problem to perform the and when it's not needed. If you then port the code to a machine which can't do this without using an and, it will still work.

Just because something works with one or two compilers on one or two types of machine, doesn't necessarily mean that it will work in ALL compilers or ALL processor architectures. Belts and braces.

--
Mats

8. So, the AND part makes the macro more robust. By the way, -out of curiosity- do you know cases (arch/os/compiler) where the code without the '& 0xffff' would not work?

Furthermore, how should I code in a platform/compiler independent manner? Any guide, book or tutorial on that?

9. Originally Posted by kalevi
So, the AND part makes the macro more robust. By the way, -out of curiosity- do you know cases (arch/os/compiler) where the code without the '& 0xffff' would not work?

Furthermore, how should I code in a platform/compiler independent manner? Any guide, book or tutorial on that?