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

J. *_*Doe 2 c++ pointers casting

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

LPVOID lpFunction;
DWORD dw = (DWORD)lpFunction; // What does it take from LPVOID?
Run Code Online (Sandbox Code Playgroud)

将会有更多的一般性解释.谢谢

Cod*_*ray 6

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

您展示的代码,

LPVOID lpFunction;
DWORD dw = (DWORD)lpFunction; // What does it take from LPVOID?
Run Code Online (Sandbox Code Playgroud)

越野车坏了.

历史上LPVOID是一个指向void的远指针(而不是指向void的指针PVOID).远/近指针的区别不再相关,因为我们不再编程为分段架构,所以现在所有这LPVOID意味着void*.它相当于PVOID(但是你今天在代码中很少看到后者,因为所有API调用都是远程调用,因此原型化LPVOID).

这种DWORD类型在历史上是一个无符号的"双字",在x86上意味着它是32位.API规范仍然保证DWORD所有支持的体系结构上都是无符号的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)
Run Code Online (Sandbox Code Playgroud)

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