windows 为什么 MAKEINTRESOURCE() 有效?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3610565/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does MAKEINTRESOURCE() work?
提问by twf
The macro is defined as:
宏定义为:
#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))
How come this can be used to indicate either a resource ID (a 16-bit unsigned int) or its name (a pointer to an array of char)? Doesn't this effectively limit the address space (on a 32-bit system) to 16-bit? Otherwise how does the system know whether I'm using an ID or a name?
为什么这可以用于指示资源 ID(16 位无符号整数)或其名称(指向字符数组的指针)?这不是有效地将地址空间(在 32 位系统上)限制为 16 位吗?否则系统如何知道我使用的是 ID 还是名称?
回答by Hans Passant
This works because Windows doesn't allow mapping pages for the first 64 KB of the address space. To catch null pointer references. But I think also to catch pointer bugs in programs that were converted from the 16-bit version of Windows.
这是有效的,因为 Windows 不允许为地址空间的前 64 KB 映射页面。捕获空指针引用。但我认为还要捕捉从 16 位版本的 Windows 转换而来的程序中的指针错误。
A side-effect is that this allows to reliably distinguish resource IDs packed into a pointer value since they'll always point to non-mappable memory.
一个副作用是,这允许可靠地区分打包成指针值的资源 ID,因为它们总是指向不可映射的内存。
回答by Alex F
MAKEINTRESOURCE macro just makes casting between numeric parameter and string pointer. The resulting string pointer is invalid and cannot be dereferenced as resource name. However, resource handling API detect such pointers by their absolute value and treat them as resource ID and not resource name. Since C-style API doesn't support overloading, they cannot define two functions like:
MAKEINTRESOURCE 宏只是在数字参数和字符串指针之间进行转换。结果字符串指针无效,不能作为资源名称取消引用。但是,资源处理 API 通过它们的绝对值检测此类指针,并将它们视为资源 ID 而不是资源名称。由于 C 风格的 API 不支持重载,它们不能定义两个函数,例如:
HICON LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName); HICON LoadIcon(HINSTANCE hInstance,UINT resourceId);
So, API developers decided to use the same function for both cases, providing MAKEINTRESOURCE macro for API users. I believe that two different functions could look better:
因此,API 开发人员决定对这两种情况使用相同的功能,为 API 用户提供 MAKEINTRESOURCE 宏。我相信两个不同的函数看起来会更好:
HICON LoadIconByName(HINSTANCE hInstance,LPCTSTR lpIconName); HICON LoadIconById(HINSTANCE hInstance,UINT resourceId);
But this is not the way Windows API is implemented. Valid resource ID is always less than minimal possible pointer value. Resource name parameter is passed to API without this macro, and its value is not restricted.
但这不是 Windows API 的实现方式。有效的资源 ID 总是小于最小可能的指针值。资源名称参数不带此宏传递给API,其取值不受限制。
回答by Adrian McCarthy
Yes, it does limit the address space, but not as much as you think. They've effectively carved out 64KB of your 4GB address space. Most, if not all, of that 64KB is already reserved for other things on Windows, so the effective loss is nothing.
是的,它确实限制了地址空间,但没有你想象的那么多。他们已经有效地分配了 4GB 地址空间中的 64KB。这 64KB 的大部分(如果不是全部)已经保留给 Windows 上的其他东西,因此有效损失不算什么。
Overall, it's a space savings, because they don't need an extra bit of information to distinguish between a pointer and an integer ID. This was invented back in the bad old days, when space was at a premium.
总的来说,它节省了空间,因为它们不需要额外的信息来区分指针和整数 ID。这是在糟糕的过去发明的,当时空间非常宝贵。