前言
在使用C语言时,我们根据自己所需会声明各种各样的数据类型,例如整形,浮点型等,了解数据在内存中的存储方式,对我们理解计算机一些底层运行逻辑和我们提高自身的“内功修为”有着很大的帮助,今天我们就先来介绍一下整形在内存中的存储方式。
一、原码、反码、补码
1.概念
首先我先介绍整数的三种表示方法:
原码:直接将二进制按照正负数的形式翻译成二进制就可以。
反码:将原码的符号位不变,其他位依次按位取反就可以得到了。
补码:反码+1就得到补码。
注意:三种表示方法均有符号位和数值位两部分,符号位都是用“0”表示正数,用“1”表示负数,符号位一般都是该数据的最高位,其中正整数的三种表示方法都相同,而负整数的三种表示方法各不相同。
例如int类型的数值5的原码,反码补码
都是:0000 0000 0000 0000 0000 0000 0000 0101
而对于-5来:
原码:1000 0000 0000 0000 0000 0000 0000 0101
反码:1111 1111 1111 1111 1111 1111 1111 1010
补码:1111 1111 1111 1111 1111 1111 1111 1011
对于整形来说:数据存放在内存中其实存放的是补码。
2.意义
计算机系统中采用补码运算的主要目的是简化计算机的设计,特别是在硬件电路的实现方面。使用补码表示可以让加减法运算统一处理,简化了计算机的算术逻辑单元(ALU)的设计,不需要单独处理正数和负数,因而减少了硬件复杂度。同时,补码表示还解决了传统符号位表示负数时存在的多个“0”的问题。接下来我举个例子:
我们将数据存储到内存后,计算机怎么将其读取出来呢?由于存储的是补码,一般人可能会想到先-1转换为反码,再符号位取反转换为原码,但是计算机并不是这样的,它的操作步骤和原码转换为补码是一样的,直接取反+1得到原码,相当与说原码和补码之间的转换是等效的,步骤都是一样的,你们可以试一试将-5的补码转化为原码,最后的数值都是一样的。有时候不得不感慨计算机语言的奇妙之处,感叹这些科学家的智慧,我特意查询了这位科学家John Wilder Tukey,是一位美国统计学家。
二、大端小端
1.概念
上面介绍了整形数据的表示方法,下面介绍两种数据的存储和读取形式:
大端(存储)模式:是指数据的低位保存在内存的高低址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式:是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高低址中。
2.意义
大端和小端的存储方式主要是用于解决多字节存储安排问题的,例如一个32位的数据如何存储在多个16位寄存器呢?不同处理器有自己规定的一种存储和数据方式,方便读取和存储数据,像KEIL,C51则为大端模式,而很多的ARM,DSP都为小端模式,例如对于我们常用的X86结构采用的是小端模式,如图所示:
以b=-10为例,它存储在内存中的补码为:11111 1111 1111 1111 1111 1111 1111 0110,写成十六进制为:0x ff ff ff f6,不难发现在内存中是以
0xf6 ff ff ff存储的。大端和小端的存储方式,对CAN 通讯中也是有着重要的启示作用,与存储方式不同的是在CAN 通讯中则是传输方式的区别,数据的高低位与高低地址的两两组合便有了intel 和motoroal这两种协议,不同的协议格式决定了对DBC文件的解读方式,以后有时间我会在电机控制专栏讲解的。
三、数据溢出及转化规则
数据类型确定了这个空间所能盛放的数据的最大值和最小值。如果使用char
型存放一个200,那么就超出了char
型数据所能表示的数据范围,程序会按照一定的规则将这个200转化为-128~127这个范围中的某个数后再去进行存储。
数据范围的表示是一个环状结构.
-
如果数据增长到最大值,则数据从最小值方向开始依次递增
-
如果数据减到最小值,则数据从最大值方向开始依次递减
通俗的来说,以char
类型数据为例,如果将200存储到char
类型的数据中,它会将200减去256,得到-56(看结果是否在-128 ~ 127范围内,如果不在继续±256,直到最后的结果在-128 ~127范围内) 存入到char
类型的数据中。其中256为char
类型能表示的数据范围(-128~127)。
同理如果将32769的数据存入
short
时,得到的将是-32767,32769减去65536得到-32767.
总结
本文通过整形数据的表达方式和大小端的存储形式这两方面讲述了整形数据在内存中的存储方式,最后了解了数据溢出及转化规则,对计算机如何处理繁杂的数据方式有了大概的理解和认识。