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

时间:2014-02-13 11:55:30

标签: c++ winapi casting

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

原始代码是:

WPARAM param = (WPARAM)(GetDlgItem(IDC_WORKFLOW).m_hWnd);
this->PostMessage(WM_NEXTDLGCTL, param, TRUE);

如果我使用静态演员:

WPARAM param = static_cast<WPARAM>(GetDlgItem(IDC_WORKFLOW).m_hWnd);
this->PostMessage(WM_NEXTDLGCTL, param, TRUE);

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

WPARAM param = reinterpret_cast<WPARAM>(GetDlgItem(IDC_WORKFLOW).m_hWnd);
this->PostMessage(WM_NEXTDLGCTL, param, TRUE);

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

在此特定情况下,此播放是否安全,如何确认?如果没有,有什么替代方案?

5 个答案:

答案 0 :(得分:4)

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

typedef UINT_PTR            WPARAM;

和_PTR后缀表示该类型足以容纳指针。

而HWND是:

 typedef HANDLE HWND;

HANDLE是:

typedef void *HANDLE;

因此void *和UINT_PTR的大小始终相同。如果你将它存储在64位应用程序中并尝试在32位应用程序中读取,那么你就会遇到麻烦。

如果你仍然认为这样做是否安全,你可以搜索Visual Studio源代码(在C:\ Program Files(x86)\ Microsoft Visual Studio 8 \文件夹中),你会发现很多行reinterpret_cast<LPARAM>(...)reinterpret_cast<WPARAM>(...)

答案 1 :(得分:2)

是的,这很好,是reinterpret_cast的目的,即“相信我,我知道我在做什么”的方法,C必须铸造。

答案 2 :(得分:1)

也许现在我们可以使用C ++ 20中的std::bit_cast作为替代方式,这应该表现得更好。

在后台,std::bit_cast使用std::memcpy,我认为您也可以使用它从HWND投射到WPARAM

答案 3 :(得分:0)

它可能适用于您的计算机,编译器以及编译器的一组非常具体的编译选项。

您正在将一种指针类型转换为另一种指针类型。那不是“安全的”。您的代码违反了严格的别名规则。这使您的编译器能够以与您的预期完全不同的方式解释您的代码。您的代码可能有效,但可能无效。您正在调用未定义的行为。

答案 4 :(得分:0)

不是一般规则。 C风格演员将尝试做正确的事。这通常意味着尝试static_cast并且只有在执行reinterpret_cast

时才会这样做

查看以下C ++代码

#include <stdio.h> 
#include <new>

class Base
{
public:
    int base;
};

class Extension
{
public:
    int extension;
};

class Derived : public Base, public Extension
{
public:
    int derived;
};

int main()
{
    Derived* der = new Derived;
    der->base = 1;
    der->extension = 2;
    der->derived = 3;

    Extension* ext = (Extension*)der;
    printf ("The value of ext->extension = %d\n",ext->extension);
    ext = reinterpret_cast<Extension*>(der);  
    printf ("The value of ext->extension = %d\n",ext->extension);
}

结果

c:\work>test
The value of ext->extension = 2    
The value of ext->extension = 1

换句话说,用reinterpret_casts盲目地替换C样式转换是不安全的。