4

I've come into contact with some weird notation in a C++ program. I'm dealing with bit shifting and I came across the LOWORD() and HIWORD() functions. I understand that LOWORD is the value of the lower 2 bytes of an integer. I also know that HIWORD is the higher 2 byes of that integer. However, I came into contact with a code snippet which looked something like this:

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

int v1 = 0x12343460;
int v2 = 0x11111111;
HIWORD(v2) = HIWORD(v1);
LOWORD(v1) = LOWORD(v2);

From what it appears, it looks as though the programmer is suggesting to place the value of one function into another function. However, that seems impossible without some serious programmer magic. Any help whatsoever in decrypting this code snippet would be greatly appreciated.

Sean
  • 592
  • 4
  • 9
  • 19
  • 3
    As they are generally defined in Win32 APIs, this cannot possibly work (except maybe the `LOWORD` one thanks to the lvalue cast nonstandard extension). If you have different definitions, you should post them. – Matteo Italia Sep 21 '18 at 00:36
  • 1
    Ok, if you "understand" what `LOWORD` and `HIWORD` is, then what exactly is your question? Nobody here has any idea what `LOWORD` or `HIWORD` is, since the definition of these mysterious functions or macros is not shown in your question. You know more about them than anyone else who has read this question. To answer the only actual question here, no, this code does not "make any sense", since how `HIWORD` and `LOWORD` works is not shown, and the only thing that anyone can do here is speculate as to what these mysterious functions might be. – Sam Varshavchik Sep 21 '18 at 00:36
  • 1
    Voted to close as lacking reproducible example. – Cheers and hth. - Alf Sep 21 '18 at 00:40
  • 1
    You need to show the *definitions* of `HIWORD` and `LOWORD`. We don't code in English :-) – paxdiablo Sep 21 '18 at 01:02
  • I don't see how this code could work. Just tried and it didn't – Severin Pappadeux Sep 21 '18 at 01:06
  • 1
    @SeverinPappadeux, there *are* ways it could work (see my answer for one of them). However, like cutting out your own heart with a blunt spoon, that doesn't make it a good idea :-) – paxdiablo Sep 21 '18 at 01:33
  • @paxdiablo Yes, I though you could make something like this work, but as far as I (and everyone else) knows from infamous windows.h header family, those are still macros and code like above won't work. Just checked with VS 2017 and Windows 10 april SDK, #include "windows.h" etc – Severin Pappadeux Sep 21 '18 at 13:57
  • HWORD and LOWORD are defined in the MSDN,. see win32. – T.S Sep 30 '19 at 07:35

3 Answers3

3

Wow, that is truly hideous code. About the only way I could see that working (as functions) is if the functions returned references to the parts of the variables passed in. In other words, something like:

#include <iostream>

unsigned short int & HIWORD(unsigned int & x) {
    return *(reinterpret_cast<unsigned short int *>(&x) + 1);
}

unsigned short int & LOWORD(unsigned int & x) {
    return *(reinterpret_cast<unsigned short int *>(&x) + 0);
}

int main() {
    unsigned int v1 = 0x11112222;
    unsigned int v2 = 0x33334444;

    std::cout << "Before: " << std::hex << v1 << ' '  << v2 << '\n';

    HIWORD(v2) = HIWORD(v1);
    LOWORD(v1) = LOWORD(v2);

    std::cout << "After : " << std::hex << v1 << ' '  << v2 << '\n';
}

This (at least on my system) generates what you're probably seeing:

Before: 11112222 33334444
After : 11114444 11114444

But, if you actually see code like that, I'd suggest one of two courses of action:

  1. Fix it. There are about a hundred better ways you could do the same thing.
  2. Leave. Just leave. Don't collect your belongings. Just get up from your chair, walk out the door, get in your car, drive off and never come back :-)

Now it's possible they may be macros rather than functions but my advice still stands regarding the two possible options.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

To fix it:

#define HIDWORD(dw, hw) LOWORD(dw) | (hw << 16)
#define LODWORD(dw, lw) (HIWORD(dw) << 16) | lw
-----------------------------------------------
v2 = HIDWORD(v2, HIWORD(v1));
v1 = LODWORD(v1, LOWORD(v2));
  • I think this is the best hypothesis. When I looked at the question I initially thought, "This is probably some type of swap." If I am correct, we are interlacing the low and high words of "v1 and v2" together in your example? – KANJICODER Nov 07 '20 at 02:59
0

Just tried code like you provided and it didn't compile

Here how those macros are defined

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

WORD is uint16_t, DWORD_PTR is uint32_t. Compiler said left side must be lvalue

Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
  • 2
    "*DWORD_PTR is uint32_t*" - only when compiling for 32bit. If you compile for 64bit, it is `uint64_t` instead. That is what the `_PTR` refers to - it is a pointer-sized integer. – Remy Lebeau Sep 21 '18 at 04:34