溢出 (你想知道的C语言 3.7)

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)
 
转载请注明出处

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值