为什么MAKEINTRESOURCE()工作?

macros被定义为:

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

这怎么可以用来表示一个资源ID(一个16位无符号整数)或它的名字(指向一个字符数组的指针)? 这是不是有效地限制了地址空间(在32位系统上)为16位? 否则,系统如何知道我是否使用了ID或名称?

Solutions Collecting From Web of "为什么MAKEINTRESOURCE()工作?"

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

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

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

是的,它确实限制了地址空间,但并不像你想象的那么多。 他们已经有效地分割出了4GB的4GB地址空间。 大部分(如果不是全部的话)64KB已经预留给Windows上的其他东西,所以有效的损失是没有的。

总的来说,这是节省空间,因为它们不需要额外的信息来区分指针和整数ID。 这是在过去不好的时候发明的,当时空间有限。