为什么MAKEINTRESOURCE()有效?

twf*_*twf 18 c c++ windows winapi

宏定义为:

#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
Run Code Online (Sandbox Code Playgroud)

为什么这可以用于指示资源ID(16位无符号int)或其名称(指向char数组的指针)?这是否有效地将地址空间(在32位系统上)限制为16位?否则,系统如何知道我使用的是ID还是名称?

Han*_*ant 22

这是有效的,因为Windows不允许映射页面为地址空间的前64 KB.捕获空指针引用.但我认为还要捕获从16位版本的Windows转换而来的程序中的指针错误.

副作用是,这允许可靠地区分打包到指针值的资源ID,因为它们总是指向不可映射的存储器.

  • @rbe 完整的历史背景可以在这里找到:[Win32 允许的最高数字资源 ID 是多少?](https://devblogs.microsoft.com/oldnewthing/20110217-00/?p=11463) 剧情剧透:前 64KB 内存在 32 位 Windows 中永久无效这一事实并不是所选分区安全的原因。这只是一个令人高兴的巧合。 (2认同)

Ale*_*x F 18

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,其值不受限制.


Adr*_*thy 6

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

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

  • 如果该值小于 64KB,则假定为整数 ID。如果它大于 64KB(一直到 4GB),则假定它是一个指针。 (3认同)