C 语言无符号与有符号整型溢出的区别

无符号整型溢出

对于无符号整型溢出,在 C 的规范中这是有定义的行为,溢出后的数会以2^(8 * sizeof(type))作模运算,也就是说,如果一个无符号字符型(1 字节,8 位)溢出了,会把溢出的值与 256 求模。

1
2
unsigned char x = 0xff; // 1111 1111
printf("%d\n", ++x); // 结果为:0

有符号整型溢出

对于有符号整型的溢出,C 的规范定义是 Undefined Behavior,也就是说,编译器爱怎么实现就怎么实现。对于大多数编译器来说,算得啥就是啥。

注意:用补码表示。

1
2
3
signed char x = 0x7f;  // 0111 1111 表示最大的正数
// 0xff就是 -1 了,因为最高位是 1 也就是负数了
printf("%d\n", ++x); // -128

++x的结果为1000 0000,因为这是补码,所以值为-128

所以,有符号整型的溢出规律一般呈环形变化。

如果还是觉得不能理解可以看一下补码的表示方法:关于补码的总结

整型溢出可能导致死循环

1
2
3
4
5
6
#define MAX_LEN 32767
short len = 0;

while (len < MAX_LEN) {
len += 2;
}

short 是 2 字节长的有符号整型类型,能表示-32768 ~ 32767范围内的整数。当 len 的值为32766时,加 2 运算使得其溢出,值为-32768,而不是32768,如此不断循环。加 1 不会出现这样的问题,当 len 为32767时,循环将会终止。

0%