Vil*_*ray 2 x86 signed integer-overflow undefined-behavior
有符号整数在x86上通过二进制补码表示,其中符号位具有该值-(2^N).这导致在-2^N和2^N - 1(例如-32768通过32767)之间的典型可表示值范围.
我很好奇如果我在我的系统上取最小有符号整数值并乘以它以-1试图"强制"一个大于我系统上有符号整数的最大可表示值的最大值,会发生什么.
#include <stdio.h>
#include <limits.h>
int main(void){
signed int x, y;
x = INT_MIN;
y = x * -1;
printf("%d\n%d\n", x, y);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这导致以下输出:
# gcc -std=c89 -pedantic int_min_test.c
# ./a.out
-2147483648
-2147483648
Run Code Online (Sandbox Code Playgroud)
我期待一个整数溢出(导致典型的值翻转),但看起来似乎没有关于xwith 的乘法操作-1.
在x86中是否INT_MIN与-1no-op 相乘?
对于 C(基于问题的原始标记,以及用 C 编写的示例代码),这是未定义的行为,所以不,C 表达式的结果INT_MIN * -1不是“无操作”,而是未定义的行为。实际上,根据观察方式的不同,观察到的结果可能会不一致,甚至可能在时间上不一致。不要这样做。
如果您想询问 x86imul指令,那是另一个问题,我相信(32 位)imulby0x80000000会0xffffffff产生0x80000000。但这与您期望在 C 中看到的内容无关。
使用gcc 4.8.5,y = x * -1;使用以下指令计算行:
neg %eax
Run Code Online (Sandbox Code Playgroud)
neg操作翻转该字的位然后加1.对于32位2的补码,结果为:
0x80000000 # Start value
0x7FFFFFFF # Flip bits
0x80000000 # Add 1
Run Code Online (Sandbox Code Playgroud)
如您所见,计算机正在完全按照您的要求执行操作.这不是一个空操作,如neg修改AF,CF,OF,PF,SF,和ZF标志.它只是所使用的二进制表示的工件.正如其他人所说,它只是未定义的行为.