简体   繁体   中英

What does type cast of DWORD on LPVOID return?

I'm sometimes confused when type casting in C++, what exactly do these return?

LPVOID lpFunction;
DWORD dw = (DWORD)lpFunction; // What does it take from LPVOID?

More of a general explanation would be appreciated. Thanks

It doesn't return anything valid or useful.

The code you've shown,

LPVOID lpFunction;
DWORD dw = (DWORD)lpFunction; // What does it take from LPVOID?

is buggy and broken.

Historically LPVOID was a far pointer to void (as opposed to a near pointer to void, PVOID ). The far/near pointer distinction is no longer relevant, as we no longer program to a segmented architecture, so now all that LPVOID means is void* . It is equivalent to PVOID (but you rarely see the latter in code today, because all API calls were far calls and therefore prototyped with LPVOID ).

The DWORD type was historically an unsigned "double word", which on the x86 meant that it was 32 bits. The API specification still guarantees that DWORD is an unsigned 32-bit type on all supported architectures.

Which brings us to the problem. DWORD is a fixed-size type, represented with 32 bits. LPVOID is a pointer, and pointers can be different sizes on different architectures. And this is not just a theoretical portability issue. It is a very practical one. On a 64-bit architecture (x86-64 being not only a supported platform for Windows, but a particularly popular one nowadays), DWORD will be 32 bits, but a pointer will be 64 bits. So when you coerce a 64-bit pointer into a 32-bit integer, you will inevitably lose some data. That's what makes the code broken. It will fail spectacularly on a 64-bit target.

If you want to coerce a pointer to an integral type, then you need to use either DWORD_PTR (a pointer-sized DWORD), INT_PTR (a signed integral representation of a pointer), or UINT_PTR (an unsigned integral representation of a pointer). Using any other type to store a pointer makes your code buggy and broken.

LPVOID lpFunction = ...;
DWORD_PTR dwpFunction = reinterpret_cast<DWORD_PTR>(lpFunction);
// (dwpFunction now contains an integer representation of the lpFunction pointer)

Speaking in a more general sense, it is best to avoid these types of casts that coerce one type into another. If you'd written it as a C++-style cast, as I did above, you'd have to write reinterpret_cast<DWORD>(lpFunction) , which would make it quite obvious that you're doing something unportable and potentially unsafe. Admittedly, there are cases where this is perfectly okay, and there are especially cases where it is required when programming to the Windows API. This drives purists nuts, but the API specification guarantees that it will work. Your code becomes unportable, but that is hardly a relevant concern when you're writing a program that uses Windows-specific APIs. Still, prefer to write the casts using the C++ style so that it is clear what you are doing is a potential problem. That way, anyone who looks at the code can check it to make sure that your cast is permissible by the rules of the API, because the compiler can't do it anymore. The cast tells it to shut up and turn off its normal warnings.

LPVOID is defined as a (Microsoft Windows style) "longword-sized pointer to void ," which is to say, "a pointer to I-don't-care-what."

You are now coercing that to be seen as a DWORD ... which you'd better know(!) occupies the same number of bytes, and storing the value of that pointer into dw . This variable now contains what used to be seen as "a memory address," but it's not an address anymore: it's a double-word integer.

This, by the way, is a very hazardous thing to do, in the sense that it makes a lot of "assumptions." It also turns a pointer-type into a non-pointer (arithmetic ...) type. This can easily result in all kinds of hard-to-diagnose bugs, and it wipes-out much of the compiler's potential ability to detect such bugs for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM