数据类型的取值范围和溢出

不知何为原码反码补码的童鞋请猛戳这里,这篇文章要说的是,数据类型的取值范围和溢出

  • 取值范围

数据类型的取值范围有一个公式:-2(n-1)~2(n-1)-1
n为整型的内存占用位数,所以int类型32位那么就是-(231)~231 -1即-2147483648~2147483647
但是,为什么最小负数绝对值总比最大正数多1???

以char为例:
-0:原码是1000 0000,补码为1 0000 0000,由于char是八位,所以取低八位0000 0000。+0:原码为0000 00000,补码为也为0000 0000,虽然补码0都是相同的,但是有两个0,既然有两个0,况且0既不是正数,也不是负数,用原码0000 0000表示就行了,这样一来,有符号的char,原码都用来表示-127~127之间的数了,唯独剩下原码1000 0000没有用

现在再来探讨一下关于剩下的那个1000 0000

-128的原码是1 1000 0000,9位,最高位符号位,再算它的反码1 0111 1111,进而,补码为1 1000 0000,这是-128的补码,发现和原码一样,但是在char型中,是可以用1000 000表示-128的。关键在于char是8位,它把-128的最高位符号位1丢弃了,截断后-128的原码为1000 0000和-0的原码相同,也就是说1000 0000和-128丢弃最高位后余下的8位相同,所以才可以用-0表示-128。这样,当初剩余的-0(1000 0000),被拿来表示截断后的-128,因为即使截断后的-128和char型范围的其他数(-127~127)运算也不会影响结果,所以才敢这么表示-128

  • 数据溢出

既然说-128和char型范围的其他数(-127~127)运算也不会影响结果,那么我们就来运算一下,运算完之后也就知道了数据溢出是怎么回事了:(注意计算机内部以补码形式进行运算的,所以运算结果为补码,补码转原码的过程为:先减一,然后符号位不变其他位取反)

-   128 + 127:
    1000 0000
+   0111 1111
=   1111 1111,符号位为1表示负数,减一得到反码1111 1110,取反得到源码1000 0001,即-1
      127+(-127):
      0111 1111
+     1000 0001
=   1 0000 0000,高位溢出,取后八位,得0
      -128+(-1):
      1000 0000
+     1111 1111
=   1 0111 1111,高位溢出,取后八位,符号位为0表示正数,所以得127
    127+1:
    0111 1111
+   0000 0001
=   1000 0000,前面我们已经讨论过,1000 0000表示-128

搞清了数据类型的取值范围和溢出,并且知道计算机内部是以补码形式进行运算的,那么也就不难理解为什么下面这个程序会输出-1了

#include<stdio.h>
int main()
{
    //1111 1111
    //1111 1110
    //1000 0001
    char c = 0xff;
    printf("%d\n",c);
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可...
    yang2yang阅读 2,273评论 1 13
  • C语言基础 编译程序 gcc xx.c,他会默认生成a.out的可执行文件,在a.out所在目录,执行./a.ou...
    帅碧阅读 644评论 1 3
  • 家庭生活里最多的矛盾就是婆媳关系引发的战争,不管是好的关系,还是坏的,最重要的那个就是中间的男人。 母...
    虎仔妈妈爱读书阅读 317评论 0 0
  • 别人有再多的不好,都不应受到不尊重,抑或口口相传,越传越离谱的不堪,即便受惩罚,也是上帝的事情,没有针锋相对的必要...
  • 你问我为什么不喜欢美国,这个世界那么大,有歌有酒有故事,但是没有你。你想把最好的都给我,可我只是很没骨气的想要一辈...
    年之未宴阅读 255评论 0 0