本小节不仅仅只是介绍数据溢出,还会借此介绍整形的数值范围、补码、有符号与无符号等问题

一、数据溢出(数值范围和补码)

面试题:指出如下代码的问题

#define MAX 255

int main(void)
{
    unsigned char A[MAX],i;  //i被定义为unsigned char

    for (i=0; i<=MAX; i++)
     {
        A[i]=i;
    }
}

i的类型为unsigned char,最高位不再用来表示符号,
而是直接参与数值的表示,所unsigned char所允许的数值范围为:

11111111  255     2的8次方-1,即100000000-1, 或 255 = 2^7 + 2^6 + .....2^0
11111110  254
...
00000001  1
00000000  0

unsigned char的数据溢出
(1)向上溢出

 11111111 + 1  进位溢出
100000000      由于char只有8位,最高位被舍弃,所以结果为00000000

向上溢出变为了最小数0

(2)向下溢出

00000000 - 1  借位溢出
11111111      借位向下溢出后,结果为11111111

向下溢出变为了最大数255


题目的问题:
i++255后就会向上溢出为0,而MAX255,所以i永远不存在大于255的情况,所以是一个死循环


二、char 的数值范围 和 数据溢出

一般情况下,char默认就是signed char,但是也有极少数编译器比较特殊,char会被默认理解为unsigned char
有符号char必须明确的写为signed charsigned不能省略,不过这种情况很少,一般char都是默认为signed char

1. 数值范围

char为有符号,最高位用于表示符号(1表示负数、0表示正数),不参与数值的表示,所以真正表示数据的只有7

76543210  一共8位

01111111  127    2的7次方-1  即 10000000-1
01111110  126
...
00000011  3
00000010  2
00000001  1

00000000  0     -------------------------

11111111  -1
11111110  -2
11111101  -3
...
10000010  -126
10000001  -127
10000000  -128  -2的7次方

char 的数值范围:(-2^7) ~ (2^7 - 1),就是-128 ~ 127

有关char的数值范围,同样不要去记忆,关键是理解,只要理解了就能推导出来

疑问:为什么在计算机有符号数(char)中,11111111就代表-111111110就代表-2

答:这个涉及到了计算机存储数据时的补码问题,有关补码后面再介绍

2. char 型数据溢出

01111111  127    2的7次方-1  即 10000000-1 
01111110  126
...
00000000  0
...
10000010  -126
10000001  -127
10000000  -128  -2的7次方
1)向上溢出
01111111+1
10000000     -128,在计算机有符号char中,10000000就代表-128

所以同样的,最大数向上溢出,就变为了最小数

2)向下溢出
10000000-1
01111111     为127,在计算机有符号char中,01111111就代表127

unsigned char一样,最大数向上溢出就变为了最小的数,最小的数向下溢出就变为了最大的数


三、unsigned int、int的数值范围 与 数据溢出

unsigned intintint位数:32bit

1. unsigned int的范围

0 ~ 2的32次方-1

11111111 1111111 1111111 1111111   2的32次方-1
...
00000000 0000000 0000000 0000000    0

2. int的范围

-2的31次方  ~  2的31次方-1

01111111 1111111 1111111 1111111    2的31次方-1
...
00000000 0000000 0000000 0000000    0   -----------
11111111 1111111 1111111 1111111    -1
...
10000000 0000000 0000000 0000000   -2的31次方

3. 溢出

最小变最大,最大边最小。


四、short、long

同样的道理,shortlong 也是一样的,只是位数不一样而已

通过以上介绍可知,只要大家理解了charunsigned char的数值范围和数据溢出,
intunsigned intshortunsigned short...等的数值范围和数据溢出,也可以非常容易的被类推出来