为什么C ++,DevStudio,数组索引有效?

时间:2018-04-26 02:37:36

标签: c++ arrays

#include <windows.h> 
#include <stdio.h>

WCHAR *HiveName[4] = {L"HKCR", L"HKCU", L"HKLM", L"HKU"};

int wmain( INT argc, WCHAR **argv )
{
    for ( DWORD i = 0x80000000; i < 0x80000004; i++ )
        wprintf(L"%lu %s\n", i, HiveName[i]);
    return 0;
}

输出:

  

2147483648 HKCR

     

2147483649 HKCU

     

2147483650 HKLM

     

2147483651 HKU

为什么会这样?

1 个答案:

答案 0 :(得分:0)

首先,正如一些程序员Dude所说,越界数组索引是undefined behavior。这意味着根据ISO C ++标准,允许编译器发出任何内容。编译器甚至可以发出加密硬盘驱动器的病毒,它仍然是符合标准的编译器。

有人说过,我对可能发生的事情有一些猜测。

在Windows上,x86用户空间进程可以使用virtual addresses from 0x00000000 to 0x7fffffff。默认情况下,0x80000000及更高版本是为内核保留的,尽管有多种方法可以将此值提高到3 GB。在任何情况下,似乎任何特定分配的限制都是2 GB,因此0x80000000或更高的索引绝对不能指向有效分配的对象。然后编译器可以自由地发出代码,假设i必须以某种方式小于0x80000000

在这种情况下,可能没有任何真正的“优化”。一个版本的MSVC编译器为数组索引操作输出the following

push    DWORD PTR wchar_t ** HiveName[esi*4]

此处,esi包含索引i。它乘以4,即sizeof(wchar_t*)数组元素。这会溢出,并且它总是给出正确的答案,因为最重要的位总是被抛出。