为何Windows SDK中INVALID_HANDLE_VALUE采用双重强制转换定义?
在Windows SDK的handleapi.h中,INVALID_HANDLE_VALUE被定义为:
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
而非直接写成((HANDLE)-1),核心原因是为了跨平台兼容性、避免编译器警告,以及遵循Windows类型设计规范,具体如下:
保证32/64位平台的一致性
HANDLE本质是void*,在32位系统占4字节,64位系统占8字节。如果直接把-1(默认是32位int类型)强制转成HANDLE,在64位环境下,不同编译器对符号扩展的处理可能不一致:有些会把32位的-1补码符号扩展成64位全1,有些则只保留低32位为1、高32位为0,这会导致64位下无效句柄的值不符合预期。
而LONG_PTR是和指针宽度完全匹配的整数类型(32位对应long,64位对应__int64),先把-1转成LONG_PTR,会在对应平台生成全1的补码值,再转成HANDLE时,就能确保是全1的指针值,无论32还是64位平台,结果完全统一。消除编译器警告
多数编译器会对“窄整数转宽指针”的操作抛出警告,比如64位环境下把32位int转成64位void*,编译器会提示精度丢失或转换不安全。先转成同宽度的LONG_PTR再转HANDLE,因为两者宽度一致,编译器不会触发这类警告,代码编译更整洁。遵循Windows类型系统规范
Windows SDK中的LONG_PTR、INT_PTR这类类型,就是专门设计用来在整数和指针之间做安全跨平台转换的中间类型。用它们作为中转,是微软官方推荐的类型转换方式,能避免因平台差异引发的隐性bug。
内容的提问来源于stack exchange,提问作者albert

