c - 数组索引上的整数溢出

标签 c integer-overflow

我在 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/

相关文章:

c - 理解 C 中的积分运算

c - 素数检查器将任何数字返回为素数。 C

c++ - 可移植分支预测提示

客户端/服务器套接字通信 (AF_UNIX)

c - C (Arduino) 中更好的枚举

在 C 的过程中调用 free

.net - 为什么会出现这个整数溢出呢?

java - 溢出如何在java中工作?

c - 有符号整数溢出 : 999999999 * 10 cannot be represented in type 'int' Error

java - php乘法奇怪的整数溢出行为