有关“警告C4312:'type cast'”的问题

时间:2010-08-25 20:14:11

标签: c++ winapi 64-bit

这是我的代码:

HWND WebformCreate(HWND hParent, UINT id)
{
    return CreateWindowEx(0, WEBFORM_CLASS, _T("about:blank"),
        WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, 100, 100, hParent,
        (HMENU)id, GetModuleHandle(NULL), 0);
}

这是我得到的警告:

warning C4312: 'type cast' : conversion from 'UINT' to 'HMENU' of greater size

这些是我的问题:

  1. 为什么编译器认为转换为更大的类型是个坏主意?
  2. 摆脱警告的最佳方法是什么? (我不想禁用它。)
  3. 像这样执行双重类型转换:(HMENU)(UINT_PTR)id摆脱警告。为什么/怎么样?
  4. 禁用“检测64位可移植性问题”(Wp64)也会消除警告。为什么弃用Wp64?我应该上电吗?

3 个答案:

答案 0 :(得分:12)

隐藏在HMENU名称后面的类型实际上是指针类型。编译器告诉你将较小的整数类型包含在较大的指针类型中是没有意义的,因为结果指针值将是“不完整的”,即高阶位如果指针值将用零填充。后者对指针类型没什么意义。

在您的特定情况下,这是安全的,因为此HMENU值实际上不应该是指向任何位置的指针。但是,编译器不知道,这就是它发出警告的原因。在演员表中使用较大的整数类型作为中间类型,警告将消失(你自己建议),因为在这种情况下你要做两个演员:小整数到一个更大的整数,以及然后是指针的较大整数。较小的整数到较大的整数是一个算术强制转换,为此,用零填充高阶位非常有意义(表示的值不会改变),因此不会有任何警告

答案 1 :(得分:4)

您正在将32位UINT转换为64位指针。这是自杀 - 你试图指出一些东西,但忘了一半的位置!你绝对必须采取UINT_PTR。当您将指针强制转换为int时,如果int与指针的大小相同,则行为才可以。否则,它是应用程序运行时的结束,因为访问违规。

编辑:
为什么编译器认为转换为更大的类型是个坏主意? 回覆。上述

摆脱警告的最佳方法是什么? (我不想禁用它。)
解决问题。这段代码几乎肯定是instacrash。

像这样执行双重类型转换:(HMENU)(UINT_PTR)id删除警告。为什么/怎么样?
这是因为将UINT转换为UINT_PTR是完全有效的 - UINT_PTR只是一个整数类型,没有数据丢失。

禁用“检测64位可移植性问题”(Wp64)也会消除警告。为什么弃用Wp64?我可以上电吗? 它被弃用了,因为实际上,我不太清楚为什么。我认为它有点太容易警告了。但是对于基本的“不要转换整体类型和指针”,你一定要把它留下来。

答案 2 :(得分:2)

  

为什么编译器认为转换为更大的类型是个坏主意?

在不同大小的类型之间进行转换通常是一个有问题的操作,因为源类型可能无法表示目标所需的所有值。

  

摆脱警告的最佳方法是什么? (我不想禁用它。)

我会说,在任何地方使用HMENU并将您的功能声明为

HWND WebformCreate(HWND hParent, HMENU id)
  

像这样执行双重类型转换:(HMENU)(UINT_PTR)id删除警告。为什么/怎么样?

UINT_PTR是一个足以容纳所有指针值的整数类型,因此警告就会消失。

HMENU是指针类型。这并不意味着hMenu的值实际上是一个指针,但这是一个不允许你隐式混合eg的hack。 HMENUHWND(因为HMENUHWND分别是struct _hMENU*struct _hWND*,它们不兼容,而{{1} s将是)。