zoukankan      html  css  js  c++  java
  • C语言数值存储溢出探讨

    C语言数值存储溢出探讨

    真数与码

    真数可以等同于我们数学上的整数,包括正整数,0和负整数。

    码是什么呢?

    码就是为了存储真数而产生的。

    计算机的存储空间不是无穷无尽的,如果未来能实现用一个无穷的二进制位来存储一个数,那么码就没有存在的必要了。

    码给各个二进制位设定了一套规则,以达到使用这些二进制位来表示真数的目的。常用的有原码,反码,补码。

    现在我们计算机中所使用的的大多是补码,下面的内容也根据补码展开。

    如果在提及码的时候没有说明是用多少位来存储的,那么就是在耍流氓

    补码

    最高位表示符号位,剩余的位表示实际的数据。

    这里我假设读者已经熟练掌握真数与补码的转化。

    如果没熟练的可以看我写的这篇文章更快的进行进制转换

    这里再简单补充一下,补码取最高位为符号位,那么在使用打表法进行快速转换时,最高位的表的值取一个负值即可。例如8位的表取这样的一个序列,-128 64 32 16 8 4 2 1

    下面着重介绍当给定的位数无法存储过大或过小的真数(溢出)时,其存储区的变化。

    假设我们在用一个8位的存储空间来存储一个数。

    其正数最大能存储127,负数最小能存储-128

    如果我给出一个真数137,需要存储到这个8位的空间中。

    如果我给出一个真数-158,需要存储到这个8位的空间中。

    显然,这会产生溢出,那么溢出后,这个存储空间内将会是什么样的内容呢?

    1583500500541

    为了解决这两个问题(正溢出和负溢出),我们需要熟悉上图的结构。

    左边的是其实际的二进制存储空间的内容

    中间的一个循环的线性表,不断重复着从127到-128,再到127,再到-128,再到127,再到-128。。。

    右边的是我们的真数

    未发生溢出时,真数与我们常规的补码转换一致,但是当真数超过所能存储的范围时,就会陷入到这样一个循环中。

    知道了这样一个对应关系之后,我们就可以通过取模运算+数数的方式来计算出发生溢出时,存储空间的实际内容。

    所以,经过短暂的计算后可得出

    真数137其对应的补码是-119即1000 1001

    真数-158其对应的补码是98即0110 0010

    下面附上代码验证。

    int main()
    {
    	int8_t a = 137;
    	int8_t b = -158;
    
    	printf("a: %0x
    ", a);
    	printf("b: %0x
    ", b);
    
    
    	return 0;
    }
    

    执行结果

    a: ffffff89
    b: 62
    

    0x89: 1000 1001

    0x62: 0110 0010

    上面所讲到的只是8位的情况,对于32位,64位也遵循同样的规律。

    虽然计算机内部使用的是位运算,计算机并不知道真数这样的概念,甚至计算机内部使用的可能是完全的另一套机制,但是上面的这种计算模型总是能够得到正确的结果。如果世上有一种无限接近现实的简单的模型,那么为什么不用呢?

  • 相关阅读:
    hashmap的一些基础原理
    关于uuid
    读锁跟写锁的区别
    栈为什么效率比堆高
    MySQL行级锁、表级锁、页级锁详细介绍
    MYSQL MyISAM与InnoDB对比
    MYSQL锁表问题解决
    mysql查询锁表语句
    三种排序方法
    正则表达式
  • 原文地址:https://www.cnblogs.com/virgildevil/p/12431138.html
Copyright © 2011-2022 走看看