数组索引上的整数溢出

jor*_*dan 1 c integer-overflow

我在32位架构上使用C语言.

如果我使用array[-2147483635]为什么C将其转换为array[13]

-2147483635 在Two的补充是 10000000000000000000000000001101b

是否需要左位并将其转换为0以便它变为 00000000000000000000000000001101b,即13???

我认为它不适合size_t.因为size_t翻译-21474836354294967264.

jot*_*tik 6

它不会转化为array[13],但适当地转化为array[-2147483635].但是,这可能仍会导致未定义的行为.例如,在32位x86上,程序集为

char f(char * a) { return a[-2147483635]; }
int g(int * a) { return a[-2147483635]; }
Run Code Online (Sandbox Code Playgroud)

可能看起来像:

f:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movzbl  -2147483635(%eax), %eax
    popl    %ebp
    ret
g:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movl    52(%eax), %eax
    popl    %ebp
    ret
Run Code Online (Sandbox Code Playgroud)

在此处查看在线示例.所以对于char数组看起来都很好,但你可以看到整数数组的溢出(movl 52(%eax), %eax其中52是4×13).这是由未定义的行为引起的,因为在32位系统上,任何数组或指针都不可能存在索引为-2147483635的元素.对于数组,它指向数组的第一个元素之前的某个元素,因此是未定义的行为.对于任何指针,如果你只有一个最大的2个32或4294967296字节的内存,并让说,array点到最后一个字节索引2 32 -1或4294967295,则-2147483635个元素必须驻留在内存地址4294967295 + ((-2147483635)*sizeof(int))4294967295 - 8589934540哪个-4294967245.这样的内存地址没有意义.

有关详细信息,请参阅§6.5.6(8)中的cppreference或C标准.