废话不说,先来一段程序,诸位童鞋们猜猜这段程序的输出:
#include<stdio.h>
#define MAX 255
int main(int argc, char **argv) {
unsigned char i, a[MAX];
for(i = 0; i <= MAX; i++) {
a[i] = i;
}
for(i = 0; i <= MAX; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
童鞋们可以在你们的计算机上跑一下上面代码,有惊喜奥
还在等待输出吗?不用等了,永远不会有输出了,因为这是个死循环。话说哪来的死循环呢?这便要谈一谈计算机整型数据的表示范围和数据溢出啦
看到这里,我们要思考:对于unsigned char i = 255;i + 1 = ?
计算机中的加减乘除并不像我们平常数学中那样,因为在数学中你已经假设了数据范围为无穷大。但在计算机中,资源是有限的,为了充分利用资源,我们规定了占有不同位的数据类型。如unsigned char,它和char一样是8位,区别是首位不用做符号位,于是有:0000 0000 - 1111 1111 ,二进制转化为十进制就是0 - 255.现在再讨论上述程序:
1111 1111
+ 1
--------------------
1 0000 0000
上面我们说了,对于各种数据类型,用于表示表示的位数是固定的,那么结果中的首位的1便会由于没地方存储而舍弃,于是你惊奇的发现 255 + 1 = 0
其实再思考上面的计算过程溢出位,我们发现按权值计算溢出位的表示大小相当于:溢出位*2^8.例如上面舍弃的1表示的实际大小为 1*2^8 = 256,
分析上面舍弃的行为,你会发现数学上有相对应的操作,它就是取模
好了,经过上面的分析,你应该会发现什么,总结一下无符号整数的计算,再类推到有符号整数
对于溢出问题,提出如下问题以供思考:
1.有符号数和无符号数之间的转化(不同数据类型之间转化)
2.无符号加法,无符号乘法
3.有符号加法,有符号乘法