1.整形在内存中的存储

  我们知道,一个变量的创建是需要在内存中开辟空间的。空间的大小是根据不同的类型决定的。那接下来我们就来了解一下整型数据在所开辟内存中到底是如何存储的:

  比如:int a=20 ; int b=-10 ;

  我们知道为a分配四个字节的空间。那如何存储呢?

1.1原码,反码,补码

  计算机中的整数有3种二进制表示方法,即原码反码补码

  均有符号位数值位两部分,符号位用‘0’表示‘正’,‘1’表示‘负’。而数值位正数的原,反,补码都相同。

  负数的三种表示方法各不相同。

      原码:直接将数值按照正负数的形式翻译成二进制就可以得到原码。

      反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

      补码:反码+1就得到补码。

  那么我们就可以将 a , b 的数据用二进制表示:

  int a=20 ; 原码:00000000000000000000000000010100

                  反码:00000000000000000000000000010100

                  补码:00000000000000000000000000010100

  int b=-10 ; 原码:10000000000000000000000000001010

                   反码:11111111111111111111111111110101

                   补码:11111111111111111111111111110110

  那数据存在内存中是存的原码,还是反码,还是补码呢?

  我们不妨通过编译器得到答案,因为正数的原,反,补码相同,所以我们用负数-10来测试:   

数据的存储——整型在内存中的存储以及大小端的概念_数据

  一个16进制的 f 等价于二进制的1111;所以可以将十六进制转化为二进制:

  11111111 11111111 11111111 11110110

  也就是上面的补码,所以我们发现:

  对于整型来说:数据存放内存中其实存放的是补码。

  为什么呢?


                 原因在于,使用补码,可以将符号位和数值域统一处理

                 同时,加法和减法也是统一处理(CPU只有加法器)此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。


  什么叫将符号位和数值域统一处理?我们通过1-1这个计算来看:

数据的存储——整型在内存中的存储以及大小端的概念_反码_02

  那第二句怎么理解呢?

    原码到补码是按位取反再+1;其实补码到原码也是按位取反再+1;

    就拿-10来说:原码:10000000000000000000000000001010

                         反码:11111111111111111111111111110101

                         补码:11111111111111111111111111110110

            补码按位取反:10000000000000000000000000001001

                     再加一: 10000000000000000000000000001010

    可以看到,补码和原码互相转换,运算过程是相同的,也就不需要额外的硬件电路了,当然,计算机硬件这块知识又多了,感兴趣的老铁可以自己去研究和学习。


1.2大小端介绍

刚才在编译器上展示内存的时候,不知道大家又发现一个问题,就是为什么存入数据的顺序是反的

数据的存储——整型在内存中的存储以及大小端的概念_数据_03

接下来,我们就要引入大小端的介绍:

  什么是大端小端:

    大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;

    小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中;

为什么会有大端和小端呢?

    这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8 bit 。但是在C语言中除了8 bit 的char 之外,还有16 bit 的short型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

    例如:一个16 bit 的short型x,在内存中的地址为0x0010,x的值为0x1122(这是16进制的表示),那么0x11为高字节,0x22为低字节,这个应该都能理解。对于大端模式,0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。而小端模式,刚好相反。我们常用的x86结构是小端模式,而KEIL C51则为大端模式。很多ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择大端模式还是小端模式。

前面这么长的概念或许还不够明了,那么我们自己来想一下:

  我们创建一个Int a=0x11223344 (16进制表示的);

  对于这个四个字节的数据,如果是你,你会怎么存储?是按照1,还是2,还是3,还是4,还是说其他存放方法?

数据的存储——整型在内存中的存储以及大小端的概念_补码_04

其实,无论怎么放都可以,你只要有相应的方法把它再取出来就好了,但是或许3,4这样的方法可能没有这么好取,或者说不够方便。所以科学家们就选择了1,2 这两种方法。听说‘大端’和‘小端’这个名字借鉴了《格列佛游记》里面的故事,感兴趣的朋友可以自己去百度,这里就不再衍生了。因此方法1就是大端,方法2就是小端了。

  知道了大端和小端,我们还可以自己写一个代码来判断自己的系统是大端还是小端:

数据的存储——整型在内存中的存储以及大小端的概念_补码_05


好,那么整型在内存中的存储以及大小端的概念就讲到这里,感谢大家的阅读!