我在 32 位架构上使用 C。
如果我使用 array[-2147483635]
为什么 C 会把它翻译成 array[13]
?
-2147483635
在二进制补码上是 10000000000000000000000000001101b
它是否取左位并将其转换为 0,使其变为
00000000000000000000000000001101b
,即13
???
我不认为它被转换为 size_t
。因为 size_t
将 -2147483635
转换为 4294967264
。
最佳答案
它不会转换为 array[13]
,但可以正确转换为 array[-2147483635]
。但是,这仍然可能导致未定义的行为。例如,在 32 位 x86 上,
char f(char * a) { return a[-2147483635]; }
int g(int * a) { return a[-2147483635]; }
可能看起来像:
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
参见在线示例 here .所以对于 char
数组来说一切看起来都很好,但是你可以看到整数数组的溢出(movl 52(%eax), %eax
其中 52 是 4×13) .这是由未定义的行为引起的,因为在 32 位系统上,索引为 -2147483635 的元素对于任何数组或指针不可能存在。对于数组,它会指向数组第一个元素之前的某个元素,因此是未定义的行为。对于任何指针,如果您最多只有 232 或 4294967296 字节的内存,并且假设 array
指向索引 232 处的最后一个字节-1 或 4294967295,那么第 -2147483635 个元素必须驻留在内存地址 4294967295 + ((-2147483635)*sizeof(int))
中,即 4294967295 - 8589934540
即 -4294967245
。这样的内存地址没有意义。
参见 cppreference或 §6.5.6(8) 中的 C 标准了解详细信息。
关于c - 数组索引上的整数溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37317482/