C语言学习day06:有/无符号取值范围/数值溢出

8bit数据最大存储值=?

一般情况下:

补码最大值=0(正数符号位)111 1111=2^7-1=127

最小值:

原码:1111 1111=-127

反码:1000 0000

补码:1000 0001=-127

有符号:

char:

char类型数据大小通常占用1BYTE=8bit

数据存储时将-0对应的区间值设为最小值=-2^7

所以,8bit数据区间=【-2^7,-2^7-1】=【-128~127】

所以由此得出:

字符型取值范围=【-128~127】;

因为知道了字符型的取值范围,我们可以推出整型的取值范围:

int:

int类型数据大小通常占用4BYTE=32bit

在前面我们说过:int的大小=4BYTE(字节)=32bit(位)

所有最大值=2^31-1(为什么是32不是31呢:是因为算的有符号位0)

最小值=-2^31;

由此得出:

int的取值范围=【-2^31,2^31-1】=【2,147,483,648,2,147,483,648-1】

long long:

long long类型的数据大小通常占用8BYTE=64bit

所以我们可以通过知道上面的方法知道范围

所以

long long的取值范围=【-2^63,2^63-1】

无符号:

数据存储在计算机中不存在符号位。

举个例子:定义一个无符号的char类型

unsigned char

这样就不在区分符号位,而是所有都是数值位

那么最大的值=1111 1111=256-1=255

最小值=0(因为无符号)

所以

unsigned char=[0,255];

由此得出

unsigned int

最大值=1111 1111 1111 1111 1111 1111 1111 1111=2^32-1

最小值=0000 0000 0000 0000 0000 0000 0000 0000=0

总结:

因为有符号位,所有一般会是2^*-1(是*-1,而不是2^*的值-1)

例子:char=8bit,它的首位=符号位,所以最大值=(2^8-1)-1=(2^7)-1=127

而无符号位,它的所有都是数值位,没有符号位

所有一般是2^*

例子:unsigned char=8bit,因为没有符号位,所以最大值=(2^8)-1=255

数值溢出:

假如现在定义一个char类型,数值=127

int main(){
    char a=127;
}

现在a+2

a=a+2;

在a没有+2之前=127

补码(正数时,原码=反码=补码):0111 1111

2的值:

补码:0000 0010

现在我们将二者补码相加:

总补码=1000 0001

总反码=1000 0000(补码-1)

总原码=1111 1111(反码除了首位,全部反过来;之前的文章里有讲)

这时从总原码可得,它的值=-127(这里的代码没有+unsigned,所以是有符号的)

所以这时会发现一个问题:

127+2=-127

我们去代码里运行试试:

int main()
{
	char a = 127;
	a = a + 2;
	printf("%d\n",a);
	
	//system("pause");
	return EXIT_SUCCESS;
}

它的运行结果:

C语言学习day06:有/无符号取值范围/数值溢出_第1张图片

这是为什么呢

因为char的最大数值=127,最小数值=-128

这里的代码是a+2,所以=-127,当我们a+1时,那么返回的值=-128

这是因为有符号位的值,发生溢出时,会导致数的正负发生变化

127的补码=0111 1111;

+2后的补码=1000 0001,这就变成了负数的补码

它的原码=1111 1111,结果=-127

而无符号中,如果溢出,则溢出的最高位会被移出舍弃掉

学习溢出,并不是让我们写溢出,而是让我们不要写出溢出!!!

溢出也就解释了有符号、无符号的区别,和数值的取值范围

而溢出的原理我们要理解,所以写了这篇文章

你可能感兴趣的:(C语言学习,学习)