我在用 C 编写的 Win32 项目中有以下代码:
const HWND window = CreateWindowExW(...);
static_assert(alignof *window == alignof (int)); // 1. Always true
assert((uintptr_t) window % alignof (int) == 0); // 2. *FALSE* in general
assert((uintptr_t) window % alignof (short) == 0); // 3. Always true, at least in my testing
<windef.h>
包含以下代码,证实了陈述1:
typedef struct HWND__ { // NOTE: This code is abridged for simplicity
int unused;
} *HWND;
陈述1.和陈述2.存在内在矛盾。陈述 3. 让我相信这种行为是 Win16 API 的延续,其中
sizeof (int) == 2
.
为什么会出现这种情况?
这是 Win32 API 中的错误吗?
HWND
可能看起来像一个指针,但它只是一个唯一标识符,其位数与指针相同,Win32 子系统可以将其用于内部句柄表查找。不要相信标头中定义的 typedef;它只是定义一个结构指针以确保它不会隐式地与其他数据类型一起使用。 (也就是说,如果它只是 uintptr_t
或 PVOID
或等效的 typedef,那么很难区分一组期望参数是窗口句柄的函数与另一组也使用 uintptr_t
来实现完全不同的东西的函数就像位图或图标句柄。)
浏览ReactOS的源代码(从
NtUserCreateWindowEx
函数开始)表明返回的句柄只是一个句柄表索引左移一位(可能是为了像你提到的传统16位兼容性)并添加到一些预置中-计算的常数基值。这并不一定意味着这就是官方 Win32 源代码实际使用的内容,但它可能会让您了解它的内部工作方式(考虑到 ReactOS 尝试为两种用户模式实现二进制兼容的操作系统)和内核模式)。