Q: 溢出的本质是什么?
A: 江河漫漫,才华会溢,箱子会满,人会吃饱。无止境增加一定会满,事物的有限性,物质和欲望增长一定会撑不住。
Q: N字节无符号整形最大值再加1会变成什么?
A: 思考1字节的情形:
unsigned char c = UCHAR_MAX;
printf("%d\n", (unsigned char)(c + 1));
0
UCHAR_MAX是0xFF, 加1等于0x100, 1被丢弃!
0000000100000f66 movb $-0x1, -0x11(%rbp) // 0xFF
0000000100000f6a movzbl -0x11(%rbp), %edi // expand to 0x000000FF
0000000100000f6e addl $0x1, %edi // 0x000000FF + 1
0000000100000f71 movb %dil, %al
0000000100000f74 movzbl %al, %esi
0000000100000f77 leaq 0x34(%rip), %rdi
0000000100000f7e movb $0x0, %al
0000000100000f80 callq 0x100000f92
Q: N字节有符号整形最大值再加1会变成什么?
A:
借用分析整形内部形态的程序:
/*
Xi Chen(511272827@qq.com)
cxsjabcabc
*/
#include <stdio.h>
#include <stdlib.h>
void dump_int_bits(int n)
{
int i, j;
int bits[32] = {0};
int orig = n;
for (i = 0; i < 4; ++i) {
unsigned char c = ((n >> (i * 8)) & 0xFF);
j = 31 - i * 8;
while(c) {
bits[j--] = c % 2;
c /= 2;
}
}
printf("%d\n", orig);
for (i = 0; i < 32; ++i) {
printf("%d ", bits[i]);
if ((i + 1) % 4 == 0)
printf(" ");
}
printf("\n");
}
int main(int argc, char *argv[])
{
int i = 100;
if (argc > 1)
i = atoi(argv[1]);
dump_int_bits(i);
return 0;
}
输入: 2147483647
2147483647
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 (MSB -> LSB)
输入: 2147483648
-2147483648
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (MSB -> LSB)
2147483647是INT_MAX, 加1之后变成了INT_MIN!
为什么会出现如何奇怪的现象? 补码模式是其内因。最高位为1代表负数,使得正数不断累加一定会变成负数!
Q: 如何判断发生了溢出(有符号数的加减法)?
A: 我们可以用更大的数据保存来确认是否溢出。我们也可以这样想,溢出一定发生在最终符号位与计算的两个数符号位相反了。如果两个数符号相反,无论如何也不会算出超出最大和最小的数值。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define PD(s) printf(#s " is: %d\n", (s))
int is_add_overflow(int a, int b)
{
if (a > 0 && b > 0 && a + b < 0)
return 1;
if (a < 0 && b < 0 && a + b > 0)
return 1;
return 0;
}
int main(int argc, char *argv[])
{
int a, b;
if(argc == 3) {
a = atoi(argv[1]);
b = atoi(argv[2]);
PD(is_add_overflow(a, b));
}
else {
PD(is_add_overflow(2147483647, 1));
PD(is_add_overflow(2147483646, 1));
}
return 0;
}
is_add_overflow(2147483647, 1) is: 1
is_add_overflow(2147483646, 1) is: 0
作者: 陈曦
环境: MacOS 10.14.5 (Intel i5)
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Linux 3.16.83 (Ubuntu)
转载请注明出处