【问题标题】:why the type castings (UINT)(void*)(DWORD) are needed? [closed]为什么需要类型转换 (UINT)(void*)(DWORD)? [关闭]
【发布时间】:2013-02-10 04:39:07
【问题描述】:

这是 MFC 的 CMap 类中默认的 HashKey 函数。

AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
  // default identity hash - works for most primitive values
  return ((UINT)(void*)(DWORD)key) >> 4;
}

我的问题是为什么需要类型转换 (DWORD)(void*)?。我猜(DWORD)可能与16位机器的兼容性事务有一些关系。但我对 void* 感到困惑。

【问题讨论】:

  • 不,没有理由。编写此代码的人根本不知道他们在做什么。
  • 不知道,但(void*)(UINT)(DWORD) 之一没用。
  • @R.. 这段代码 sn-p 来自“Programming Windows with MFC”
  • 可能有人在做某事。
  • @R.. 考虑到您不知道该函数的历史或原始程序员的意图,建议编写它的人不知道他们在做什么有点天真。 Hans Passant 解释说,在最初编写代码时这种疯狂。

标签: c++ c mfc casting


【解决方案1】:
template<class ARG_KEY>
AFX_INLINE UINT AFXAPI HashKey(ARG_KEY key)
{
    // default identity hash - works for most primitive values
    return (DWORD)(((DWORD_PTR)key)>>4);
}

这就是今天这个函数的样子。您的版本来自一个非常旧的 MFC 版本,它足够旧,仍然支持 16 位程序。 MFC 于 1992 年首次发布,当时是 Windows 版本 3。MFC 版本 1.0 到 2.5 支持 16 位目标。该函数的当前版本适用于 32 位和 64 位代码。

在 16 位代码中,一个可供选择的选项是内存模型。您可以选择便宜的 16 位 near 指针或昂贵的 32 位 far 指针。所以额外的 void* cast 会将值修剪为内存模型大小。

【讨论】:

    【解决方案2】:

    这里需要转换为DWORD(双字)来告诉CPU他需要移动哪些字节,在这种情况下他只移动DWORD位。(void*)转换是为了让你刚刚得到的数字移位 4 次到指针(转换为通用地址大小)。

    void* 的大小在操作系统(32b 系统或 64b 系统)之间可能不同,因为您必须执行此转换。

    最后一次转换为(UINT) 是将指针转换为无符号整数以将内存地址作为数字获取。

    【讨论】:

      【解决方案3】:

      转换为DWORD 会将大小减小为DWORD

      转换为void* 会将大小减小为指针。

      无法从这些转换中推断出更多信息,并且在现实环境中它是矫枉过正的,但期望优化编译器不会通过这些转换做任何不必要的工作是公平的。

      【讨论】:

      • 但这不就是 sizeof (DWORD)==sizeof( void*) 吗?所以铸造就没有意义了?
      • 机器上的指针大小不同。在 64 位机器上 void * 是 64 位。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 2013-01-16
      • 2011-12-20
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多