为何C++(DevStudio环境)中此超大索引数组代码可正常运行?
为什么这段使用超大索引值的C++代码能正常工作?
这背后的核心是32位无符号整数的算术溢出特性,再结合Visual Studio(DevStudio)32位编译环境下的指针运算规则,具体拆解如下:
1. 关键数值与类型梳理
DWORD是Windows定义的32位无符号整数,范围覆盖0到0xFFFFFFFF。- 循环变量
i的取值是0x80000000到0x80000003,对应十进制的2147483648至2147483651。 - 数组
HiveName是包含4个WCHAR*元素的全局数组,在32位系统中每个指针元素的大小为4字节(sizeof(WCHAR*) == 4)。
2. 数组索引的本质是指针算术
在C++中,数组名在表达式里会自动退化为指向第一个元素的指针,因此HiveName[i]等价于:
*(HiveName + i)
指针加法的计算逻辑是:指针起始地址 + i * sizeof(元素类型)。
3. 无符号整数的溢出截断机制
计算i * sizeof(WCHAR*)时,由于32位无符号整数的最大值是0xFFFFFFFF,超过这个值的运算会被截断为低32位:
- 当
i = 0x80000000:0x80000000 * 4 = 0x200000000,截断后为0x00000000 - 当
i = 0x80000001:0x80000001 * 4 = 0x200000004,截断后为0x00000004 - 当
i = 0x80000002:0x80000002 * 4 = 0x200000008,截断后为0x00000008 - 当
i = 0x80000003:0x80000003 * 4 = 0x20000000C,截断后为0x0000000C
4. 最终的指针指向匹配数组合法索引
把截断后的偏移量加到HiveName的起始地址上,正好对应数组的合法元素位置:
HiveName + 0x00000000→ 指向HiveName[0](L"HKCR")HiveName + 0x00000004→ 指向HiveName[1](L"HKCU")HiveName + 0x00000008→ 指向HiveName[2](L"HKLM")HiveName + 0x0000000C→ 指向HiveName[3](L"HKU")
重要提醒:这是依赖环境的未定义行为!
这段代码能运行完全是32位环境下的巧合,属于C++标准中的未定义行为:
- 切换到64位编译环境时,
0x80000000 * 8不会溢出,会指向完全无关的内存地址,直接导致程序崩溃。 - 编译器优化选项、全局变量内存布局的变化都可能打破这个巧合。
绝对不能在生产代码中使用这类依赖环境特性的逻辑!
内容的提问来源于stack exchange,提问作者Vince_Fatica
相关产品推荐
相关产品推荐

