将此c-cast更改为reinterpret_cast是否安全?

dew*_*rde 7 c++ winapi casting

我正试图从我正在处理的一些代码中删除一个c风格的演员,我担心唯一的选择.

原始代码是:

WPARAM param = (WPARAM)(GetDlgItem(IDC_WORKFLOW).m_hWnd);
this->PostMessage(WM_NEXTDLGCTL, param, TRUE);
Run Code Online (Sandbox Code Playgroud)

如果我使用静态强制转换:

WPARAM param = static_cast<WPARAM>(GetDlgItem(IDC_WORKFLOW).m_hWnd);
this->PostMessage(WM_NEXTDLGCTL, param, TRUE);
Run Code Online (Sandbox Code Playgroud)

我收到错误'static_cast':无法从'HWND'转换为'WPARAM',因为底层类型之间没有有效的转换.这给我留下了"魔鬼的选择":

WPARAM param = reinterpret_cast<WPARAM>(GetDlgItem(IDC_WORKFLOW).m_hWnd);
this->PostMessage(WM_NEXTDLGCTL, param, TRUE);
Run Code Online (Sandbox Code Playgroud)

据我所知,如果static_cast是不可能的,并且这与constness无关,那么C-cast无论如何都必须进行reinterpret_cast,这意味着底层代码必须返回,这意味着这是安全的(第3点)在评论中).但是我想在更改代码之前确认一下.

在这个特定情况下,这个演员是否安全,我该如何确认?如果没有,有什么替代方案?

mar*_*inj 5

它是安全的,因为WPARAM定义为:

typedef UINT_PTR            WPARAM;
Run Code Online (Sandbox Code Playgroud)

_PTR 后缀表示类型足够大,可以容纳一个指针。

而 HWND 是:

 typedef HANDLE HWND;
Run Code Online (Sandbox Code Playgroud)

其中句柄是:

typedef void *HANDLE;
Run Code Online (Sandbox Code Playgroud)

所以 void* 和 UINT_PTR 的大小总是相同的。如果您将其存储在 64 位应用程序中并尝试在 32 位应用程序中读取,那么您会遇到麻烦。

如果您仍然担心进行此类转换是否安全,您可以搜索 Visual Studio 源代码(在 C:\Program Files (x86)\Microsoft Visual Studio 8\ 文件夹中),您会发现很多带有reinterpret_cast<LPARAM>(...)和的行reinterpret_cast<WPARAM>(...)

  • 您可以安全地以 32 位类型存储 64 位 HWND。请参阅 http://stackoverflow.com/questions/18266626/what-is-windows-handle-range-on-a-64-bits-application (3认同)