基础数据在内存中的存储-C语言

在计算机中所有的数据存储都是二进制

1  十进制与二进制的转换

1.1 二进制转十进制 

         假如数据10.101,对应各个位数 为  ab.cde ,则转换为十进制的数据
         a*2的1次方+ b*2的0次方+c*2的-1次方+d*2的-2次方 +e*2的-3次方 
         1*2(1)+0*2(0) + 1*2(-1)+0*2(-2)+1*2(-3)

1.2 十进制转二进制 

        整数:除2取余,逆序排列,用2整除十进制数,得到 商 和余数,然后在用2整除商,再得到商和余数,循环进行,直到商为0 ,最后把余数逆序排列。
        以下以10为例
       10(十进制)  
                商    余数
       10/2  5     0
       5/2    2     1
       2/2    1     0 
       1/2    0     1
       1010(二进制)
        小数 :乘2取整,顺序排列,用2乘十进制小数,得到积,把整数部分取出,再用2乘余下的小数部分,又得到一个积,再把积的整数部分取出,循环进行,直到积中的小数部分为零,或者达到要求的精度,最后把整数部分顺序排列
       例1 
       0.125(十进制)
--------------------------------
                     积       整数部分
       0.125*2  0.25     0
       0.25*2    0.5       0
       0.5*2      1.0       1  
        0.001(二进制)

       例2

  0.11(十进制)
--------------------------------
0.11 *2   0.22   0
0.22*2    0.44   0
0.44*2    0.88   0
0.88*2    1.76   1
0.76*2    1.52   1
        0.52*2    1.04   1
        0.04*2    0.08   0
        。。。。。。。
       无穷尽,如果要用32个二进制位存储这个数据,只能舍弃低位,保留高位。
       得到二进制数0.0001110...

2、char  int  short  long 存储  

      对于这几种类型的变量,都是用来存储 整数数据, 只不过因为所占内存大小不同而表示的数据的范围不同。
      看代码的时候要分两个层面:
      (1)代码层面,代码根据语法是如何写的。
      (2)计算机层面,编译器是如何翻译的。
       比如 char 类型,有的人说它是字符类型,存储的是字符,这个理解是不全面的。
       char  a = 1;  char 占1个字节可以表示数据 0-255,当然可以存储整数数据1.
       char a = '1';   单引号括起来的是字符数据,这是我们人类理解的概念,人在写代码的时候是能看明白的,但是计算机不明白,这就要用编译器来给它翻译过来,最终计算机存储的是 字符'1' 的ascii码,其实这个ascii码也是个整数数据。
     
        最终 整数数据 都转化成二进制存储到了计算机中,并且用的是补码。

2.1 为什么要补码 

      如果只有 大于0的数和加法,那么就不需要补码这个东西。

    (1)计算机硬件支持加法 ,如果要支持减法要额外硬件电路,但是减法可以用加法加上一个负数来代替,所以按照这个思路就省了这部分硬件。
    (2)模的概念
             a 如果一个数据的范围是 0-9,那么就是有10个有效状态,10就是这个数据的模
             b 在模的概念下    假定模 是M  ,   X+Y = M ,我们说X与Y 互补。
             c  两个互补的数在模的概念下  可以互为 负数 :比如
                 时钟 一圈的数字  是 0-11,它的模是12,  那么如果我现在在0初去转表针,想转到3的位置,则
                 我可以是正转  3下,也可以反转9下,所以在模为12的这个系统下,可以用3代表-9。
    (3)对于一个字节的char 变量来说 ,占8bit ,可以表示256个状态,表示非负数  0-255,模为256.
             当数据为 1111 1111 时,再+1 则得到的数据 为 1 0000 0000,最终会舍弃最高位的1,保留0000 0000,这样一圈又回归到0了。
             如果要表示负数,则一分未二,128个负数,128个非负数,最高位为符号位,当为1时,表示负数,0时表示非负数。

2.2  如何求补码 

     (1)非负数补码 =  原码
     (2)负数补码 = 反码+1,计算规则是,符号位不变,其他位按位取反,最后这个数据+1
      比如  -1 如下算法
      0000 0001   正1
      1000 0001   如果是负数,则符号位为1
      1111 1110   符号位不变,其他位按位取反
      1111 1111   再+1 得到-1的补码。
      如下计算:
      1-1 --》 1+(-1) --》0000 0001 + 1111 1111 = 1 0000 0000 溢出,舍弃最高位,是不是又回归0了?
     (3)1000 0000 表示的数字是多少?
        1000 0000 表示的数字 是 -128,而不是 -0;
        -----------------------------------------------
        假定有 -0这个数,则在内存中
        1000 0000 
        1111 1111  符号位不变,其他取反
        10000 0000  再加1溢出,舍弃最高位,内存中依然是 0000 0000;
        -----------------------------------------------
        -128的补码是按照以下方法算的,因为一个字节最高位是符号位,没法表示128,所以算的的时候又借了一个字节
        1000 0000  1000 0000  在16位中-128原码
        1111 1111  0111 1111  取反
        1111 1111  1000 0000  +1得出16位中-128的补码,存到1字节中,舍弃高位,为 1000 0000 
       

3 float  double数据的存储

       float 和 double 数据在内存中的存储方式相同,只不过由于所占字节大小不同而导致数值范围和精度不同。
       以下以float数据为例,4个字节按照如下分配:
       
       
 
       (1)科学计数法
        对于 十进制数 223.456,换算成科学计数法  2.23456 * 10的2次方      
        对于二进制小数 1101.111 换算成科学计数法 为 1.10111 * 2的3次方

       (2)在计算机内部,float数的存储,先换算成二进制的 科学计数法形式,然后分别把 尾数和指数部分存储到内存中。
         比如  1.10111*2的3次方,则在 8位指数位中要存储 3 ,23位尾数位要存储 110111。
         对于二进制数来说,最高位永远是1 所以最高位1就省略了,23位二进制位其实表示了24位尾数,所以存的是10111,
         由于指数部分有正负 ,范围是-127--128,在这里按照移位存储,3+127 ,所以存储的是127+3
         对于1101.111在内存中存储的是如下:
         
       (3)对于以下代码
               float a = 0.125;
               float b = 0.123;
               根据十进制转化为二进制的算法,a是有穷的,并且在23位尾数中可以完全存储,所有内存中存的就是0.125;
               对于b来说,转化的二进制数是无穷的,当把尾数放到23位二进制位存储的时候必然要舍弃低位数据,所以这里的存储肯定是不准确的。
               -------------------------------------------------------------------------------------
               所以对于一个  int a_int 来说,可以写出 if(a_int == 2)这样的表达式。
               对于 float a_float 来说,不能写这样的if(a_float == 1.2)这样的表达式。
               同样swtich语句可以 switch(a_int),而不能switch(a_float)。



     







         

     




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值