C++中什么经常会运用到char类型,也会将char类型作为循环语句的循环条件,但往往这里最容易出现错误,容易出现溢出,进入死循环。这里我们就来简单介绍下为什么会出现这种情况。
首先,了解下char类型的取值范围:
char分为无符号(unsigned)和有符号(signed)两种:
无符号(unsigned)的取值范围:0~255;
有符号(signed)的取值范围为:-128~127.
一般我们常用char来声明一个变量,编译器默认为有符号的,即范围为:-128~127.
常见溢出问题:
知道了char类型的取值范围后,就容易理解为什么会出现溢出了。出现溢出的地方很多都是因为将char类型的变量作为了循环语句的条件部分,这样就很容易出现溢出,这里讲解一下char类型的自增情况。
一般作为循环条件时,char类型往往被赋值了int类型,如char i = 0,然后i进行自增。
当i是无符号型时,取值范围为-128 ~ 127,当i=127后再进行自增的时候,这时i就不是等于128了,而是等于-128;当i= -128,再进行自减的时候就不是等于-129,而是等于127.
当i是有符号型的时候,取值范围为0 ~ 255,当i = 255时,再进行自增,这时i=0,而不是等于256;当i=0,进行自减的时候i= 255,而不是-1.
这是因为char型对于有符号型,前24位永远和倒数第8位一样,对于无符号型,前24位永远为零。
造成上面的结果的原因:
当为有符号型时,当i = 127时,二进制为:0....0 0111 1111,然后加1后,按照上面的原理,变为:1....1 1000 0000,结果i = -128;当i=-128时,减1,二进制变为:0....0 0111 1111,结果i = 127.
当为无符号时,当i=255时,二进制为:0....0 1111 1111,加1后,按照上面的原理,变为:0....0 0000 0000 ,结果为i= 0;当i = 0时,减1,二进制为:0...0 1111 1111,结果为255.
下面通过一个实例来说明:
#define s8 char static int k = 0; void func() { s8 i = 0; for(i = 0; i < 128; i++) { k += i&3; } printf("k = %d ", k); }
这里很多人可能会动笔就计算,算得 k= 192,但结果是错的。
原因:注意i为一个char类型,且为有符号型,并被赋初值0,这里当i = 127的时候,程序会正常进行,然后i自增,变为-128,最后还是满足条件,程序并不会终止,这样就出现了char类型的溢出,程序进入死循环。此时,要么改变循环中的条件,改为:i < 127;或者将i的类型改为int型。