LPVOID上的DWORD类型转换返回什么?

时间:2016-06-26 14:59:53

标签: c++ pointers casting

在C ++中使用类型转换时,我有时会感到困惑,这些回归究竟是什么?

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

更多的一般性解释将不胜感激。感谢

2 个答案:

答案 0 :(得分:6)

它不会返回任何有效或有用的内容。

您已展示的代码

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

有缺陷并且坏了。

历史上LPVOID是指向void的远指针(而不是指向void的近指针,PVOID)。远/近指针的区别不再相关,因为我们不再编程为分段架构,所以LPVOID表示void*均为PVOID。它等同于LPVOID(但您今天很少在代码中看到后者,因为所有API调用都是远程调用,因此使用DWORD进行原型设计。)

DWORD类型在历史上是一个未签名的&#34;双字&#34;,在x86上意味着它是32位。 API规范仍然保证{<1}}是所有支持的体系结构上的无符号32位类型。

这给我们带来了问题。 DWORD是固定大小的类型,用32位表示。 LPVOID是一个指针,指针在不同的体系结构上可以有不同的大小。这不仅仅是理论上的可移植性问题。这是一个非常实用的。在64位架构上(x86-64不仅是Windows支持的平台,而且是当今特别受欢迎的平台),DWORD将是32位,但指针将是64位。因此,当您将64位指针强制转换为32位整数时,您将不可避免地丢失一些数据。这就是破坏代码的原因。它将在64位目标上失败。

如果要强制指向整数类型的指针,则需要使用DWORD_PTR(指针大小的DWORD),INT_PTR(指针的带符号整数表示),或者UINT_PTR(指针的无符号整数表示)。使用任何其他类型来存储指针会使您的代码出错并且损坏。

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

从更一般的意义上讲,最好避免将这种类型强制转换为另一种类型的强制转换。如果你把它写成C ++风格的演员阵容,就像我上面所做的那样,你必须写reinterpret_cast<DWORD>(lpFunction),这会让你很明显你做了一些不可移植的事情。可能不安全。不可否认,有些情况下这是完全可以的,特别是在编写Windows API时,需要的情况。这驱动纯粹主义者坚果,但API规范保证它将起作用。您的代码变得不可移植,但是当您编写使用Windows特定API的程序时,这几乎不是一个相关的问题。仍然,更喜欢使用C ++样式编写演员表,以便明确您正在做的是潜在的问题。这样,任何查看代码的人都可以检查它以确保API的规则允许您的强制转换,因为编译器不能再这样做了。演员告诉它关闭并关闭其正常警告。

答案 1 :(得分:3)

LPVOID被定义为(Microsoft Windows风格)“指向void的长字大小的指针”,也就是说,“指向I-don的指针”叔转交什么“。

您现在强迫被视为DWORD ...您最好知道(!)占用相同的字节数,并存储该值指向dw的指针。这个变量现在包含以前被视为“内存地址”的内容,但它不再是地址了:它是一个双字整数。

顺便说一下,这是一件非常危险的事情,因为它会产生很多“假设”。它还将指针类型转换为非指针(算术...)类型。这很容易导致各种难以诊断的错误,并且它消除了编译器为您检测此类错误的潜在能力。