在C ++中使用类型转换时,我有时会感到困惑,这些回归究竟是什么?
LPVOID lpFunction;
DWORD dw = (DWORD)lpFunction; // What does it take from LPVOID?
更多的一般性解释将不胜感激。感谢
答案 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
的指针。这个变量现在包含以前被视为“内存地址”的内容,但它不再是地址了:它是一个双字整数。