C 语言整形溢出结果讨论

查看:76
本文介绍了C 语言整形溢出结果讨论的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

我是在编译器里用sizeof(int) 输出 4
说明我这是4个字节32位的编译器。

int a = 0x7fffffff; //有符号的 范围是 -2^31~2^31 = 2147483638 = 0x7fffffff
unsigned int b = ; //无符号的 有符号的话就是 0~2^32  = 4294967296 = 0xffffffff
 

那么根据c语言的定义

unsigned int溢出后:数会以2^(8*sizeof(type))作模运算

signed int 溢出后:undefined behavior

所以下面的代码输出为什么是?而且我把变量定义为sign 和 unsigned对输出的结果都没有影响,为什么?

printf("a: %d\n", a);  // 输出 a: 2147483647
printf("a: %d\n", a+1);  // 输出 a: -2147483648

谢谢大神们的指教!

解决方案

为了叙述方便,假设只有 3bit 表示一个整数。
一个 signed 的整型,表示范围是 -4 ~ 3,unsigned0 ~ 7。对于signed型,哪个二进制表示-4 -3 -2 ... 等有多种映射的方式。所以人们需要找一种比较好的方式,最终使用的方式就是现在的补码。
表示的方式就是:

二进制  unsigned  signed
000  0  0
001  1  1
010  2  2
011  3  3
100  4 -4
101  5 -3
110  6 -2
111  7 -1

这里多说一句对于signed负数a,其对应的二进制的转换成unsigned的b满足关系:a = b - 8

这个做的好处就是 unsigned signed 的加法(包括减法)是一样的运算方式。。。比如1+4=51+(-4) = -3 他们的表示二进制都是001+100=101
所以无论是unsigned还是signed他们其实计算机里都是相同的运算规则(加减法),只是"输出"的时候100被作为unsigned被解释为4,signed被解释为-4,而变量的类型说明了着一串二进制如何解释

对于函数printf,你有没有发现,其实他的声明只规定了第一个参数的类型,并没有规定后面参数的类型。这种函数其实是C语言里可变参数的函数类型。printf 是根据第一个参数中的%d之类的占位参数确定后面有几个参数以及占用了多少个字节。printf("%d %f\n",a,b) 的时候,通过%d printf 就把第二参数认为是signed占4个字节,然后再就知道了第三个参数的起始地址:

所以不论 a 是 unsigned 还是 signed a = 3(011) 加 1之后都是100,然后由于%d的原因printf 把其解释为signed得到-4.

这篇关于C 语言整形溢出结果讨论的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆