【问题标题】:Why does MAKEINTRESOURCE() work?为什么 MAKEINTRESOURCE() 有效?
【发布时间】:2011-04-06 08:24:49
【问题描述】:

宏定义为:

#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))

为什么这可以用来指示资源 ID(16 位无符号整数)或资源名称(指向 char 数组的指针)? 这不会有效地将地址空间(在 32 位系统上)限制为 16 位吗?否则系统怎么知道我用的是ID还是名字?

【问题讨论】:

  • 这些宏总是让我感到困惑。为什么他们不只是实现两个单独的函数,一个接受整数 ID,另一个接受字符串......
  • 谢谢,这正是我想要的。
  • @dreamlax:不这样做实际上解决了它最初创建的问题之一;)DLL中的所有数据和函数都被分配了一个序数,并且序数可以在适当的位置使用如果你愿意的话。这将 DLL 中可用序数的数量限制为 65K(具有讽刺意味的是,由于这个宏的存在以及它如何与GetProcAddress 交互)。如果您想通过拥有多个版本的函数来保持 DLL 版本之间的 ABI 兼容性,每个版本都有唯一的序数,那么阻塞的函数越少越好。

标签: c++ c windows winapi


【解决方案1】:

是的,它确实限制了地址空间,但没有你想象的那么多。他们有效地从您的 4GB 地址空间中挖出了 64KB。这 64KB 中的大部分(如果不是全部)已经为 Windows 上的其他内容保留,因此实际损失不算什么。

总的来说,它节省了空间,因为它们不需要额外的信息来区分指针和整数 ID。这是在过去糟糕的时候发明的,当时空间非常宝贵。

【讨论】:

  • 感谢您的回复。但我不明白为什么它只需要 64KB。资源 ID 是 16 位整数,指针是 32 位长。它不会将指针的可寻址空间减少到 16 位长吗?
  • 如果值小于64KB,则假定为整数ID。如果它大于 64KB(一直到 4GB),则假定它是一个指针。
  • 请记住,您不会通过此宏传递字符串资源名称,而只能传递整数资源 ID。它确实将整数资源 ID 限制为 16 位,但 IIRC 它们已经是二进制资源格式本身。
  • 这也适用于 DLL 序数,并允许您导入名称已被剥离的数据和函数。基本上,对于 Win32 API 中带有指向 C 字符串的指针的少数函数,您可以选择使用它来引用没有实际名称的东西。这项工作的所有场景几乎没有实际需要区分超过 64k 的唯一未命名项目:)
【解决方案2】:

MAKEINTRESOURCE 宏只是在数字参数和字符串指针之间进行转换。结果字符串指针无效,不能作为资源名称取消引用。但是,资源处理 API 通过它们的绝对值检测这些指针,并将它们视为资源 ID 而不是资源名称。由于 C 风格的 API 不支持重载,因此它们无法定义两个函数,例如:

HICON LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName); HICON LoadIcon(HINSTANCE hInstance,UINT resourceId);

因此,API 开发人员决定对这两种情况使用相同的函数,为 API 用户提供 MAKEINTRESOURCE 宏。我相信两个不同的函数看起来会更好:

HICON LoadIconByName(HINSTANCE hInstance,LPCTSTR lpIconName); HICON LoadIconById(HINSTANCE hInstance,UINT resourceId);

但这不是 Windows API 的实现方式。有效资源 ID 始终小于最小可能的指针值。资源名称参数传递给 API 没有这个宏,它的值不受限制。

【讨论】:

  • 这是一个很好的答案
【解决方案3】:

这是因为 Windows 不允许为地址空间的前 64 KB 映射页面。捕获空指针引用。但我也想在从 16 位版本的 Windows 转换的程序中捕获指针错误。

副作用是这样可以可靠地区分打包到指针值中的资源 ID,因为它们总是指向不可映射的内存。

【讨论】:

  • +1 历史记录。对于指针的限制,这似乎是一个合理的理由。
  • @rbe 完整的历史背景可以在这里找到:What is the highest numerical resource ID permitted by Win32? 剧透:前 64KB 内存在 32 位 Windows 中永久无效的事实并不是选择分区的原因安全的。这只是一个快乐的巧合。
猜你喜欢
  • 2020-07-05
  • 1970-01-01
  • 2013-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 2018-01-04
  • 2021-05-09
相关资源
最近更新 更多