C语言零基础第17讲:数据在内存中的存储

发布于:2025-08-17 ⋅ 阅读:(11) ⋅ 点赞:(0)

目录

1.整数在内存中的存储

2.大小端字节序

2.1 什么是大小端?

2.2 为什么会有大小端之分?

2.3 练习1   

2.4 练习2

2.5 练习3

2.6 练习4

2.7 练习5

2.8 练习6

3.浮点数在内存中的存储

3.1 浮点数的存储

3.2 浮点数存的过程

3.3 浮点数取的过程

3.4 题目解析


正文开始

1.整数在内存中的存储

        我们先来回顾一下,整数的表示方法:

  1. 整数的二进制表示方法有3种:原码、反码、补码。
  2. 有符号整数的最高一位为符号位, 0表示正,1表示负,其余位为数值位。
  3. 无符号整数没有符号位,所有的位都用来表示数值。 

        我们再来回顾一下,原码、反码和补码的概念:

  1. 原码:真值的符号部分用0或1来表示,真值的数值部分用二进制来表示。
  2. 反码:原码的符号位不变, 其他位取反。
  3. 补码:反码 + 1。
  4. 原码→补码:符号位不变,取反+1。
  5. 补码→原码:符号位不变,取反+1。 
  6. 正整数的原、反、补都相同。
  7. 负整数的原、反、补各不相同。

        我们还需要知道的是:

  1. 在计算机系统中,数值一律用补码来表示和存储。
  2. 原因在于,使用补码,可以将符号位和数值域统一处理。
  3. 同时,加法和减法也可以统一处理(CPU只有加法器)。
  4. 此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

2.大小端字节序

        请看代码:

        我们发现:0x11223344是以字节为单位,倒着存储的,即44332211。这是为什么呢?

2.1 什么是大小端?

        刚刚的变量a,是int类型,大小为4个字节。像这样,超过1个字节的数据,在内存中存储的时候,就有存储顺序的问题了。按照不同的存储顺序,分为大端字节序存储和小端字节序存储,概念如下:

  1. 大端模式:数据的低位放在高地址处,高位放在低地址处。
  2. 小端模式:数据的低位放在低地址处,高位放在高地址处。

        简而言之:

  1. 大端模式:正着存,如0x11223344→11 22 33 44。
  2. 小端模式:倒着存,如0x11223344→44 33 22 11。

2.2 为什么会有大小端之分?

2.3 练习1   

  1. 在计算机系统中,数据的存储是以字节为单位的。
  2. 每个地址单元都对应着1个字节,1个字节有8个比特位。
  3. char是1个字节,但short是2个字节,int是4个字节......
  4. 对于超过1个字节的数据,它就需要分为多个字节来存储了,也就出现了存储顺序问题。
  5. 对于32位和64位这些处理器,由于寄存器的宽度大于1个字节,必然存在着顺序问题。
  6. 我们常用的x86结构是小端模式,而KEIL C51则为大端模式。
  7. 很多的ARM、DSP都为小端模式。
  8. 有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

        请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)——百度笔试题

        我们可以以1为例,来进行大小端的判断。

        如果是大端模式,即00 00 00 01,我们取出第一个字节,应该得到00。

        如果是小端模式,即01 00 00 00,我们取出第一个字节,应该得到01。

2.4 练习2

        请看代码:

        这道题与整数在内存中的存储有关。

        我们来看一下结果:

        我们再看另一种情况,如果是以%u的形式打印呢?

2.5 练习3

        我们来看一下分析及结果:

        我们再看一道类似的题目:

2.6 练习4

2.7 练习5

        再看一道类似的题目:

2.8 练习6

        对于ptr[-1],我们可以看看图解:

        我们再来看一下*ptr2的图解:

        运行结果如我们所见:

        上述代码运行的环境为32位环境,如果是64位环境,a是8字节的地址,强制转换为4字节的int类型,就会破坏地址的完整性了。 

3.浮点数在内存中的存储

        请看代码:

        如上,我们可以发现,浮点数的存储方式,和整型是有差异的。

3.1 浮点数的存储

        在上面的代码中,n和*pFloat在内存中明明是同一个数,为什么以浮点数和整数的视角解读,结果会有这么大的差异呢?

        要理解这个结果,一定要搞明白浮点数在计算机内部的表示方法。

        根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:

  1. S也叫数符,0表示整数, 1表示负数,用来决定浮点数的符号。
  2. M也叫尾数,是一个二进制的定点小数,一般用原码表示。
  3. E也叫阶码,是一个二进制的定点整数,一般用移码来表示。

        我们来看一个例子:

        IEEE754规定:

  1. 对于32位的浮点数(float),最高1位存储的是符号位S,后面8位存储的是指数E,剩下23位存储的是有效数字M。
  2. 对于64位的浮点数(double),最高1位存储的是符号位S,后面11位存储的是指数E,剩下52位存储的是有效数字M。

3.2 浮点数存的过程

        前面提到过,根据IEEE 754标准,M都是写成1.xxxxxx的形式。可以发现,任何一个浮点数,第一位都是1。

        IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以不用存这个1,只存后面的xxxxxx部分即可

        比如,在存1.01的时候,只存01,等到读取的时候,再把第一位加上去。

        这样做的目的是,节省1位有效数字。以32位浮点数为例,留给M的只有23位,将第一位舍去后,相当于可以存24位有效数字了。

        至于指数E,它是一个无符号整数(unsigned int)

        这意味着,如果E为8位,它的取值范围就是0~255;如果E为11位,它的取值范围就是0~2047。但是,我们知道,有时候E是会出现负数的,比如:0.5为(-1)^0*1.0*2^(-1),这里的E就是-1。所以IEEE 754规定,存入内存时,E的真实值必须再加上一个偏置值。对于8位的E,偏置值为127;对于11位的E,偏置值为1023。也就是,根据IEEE 754,对于n位的E,偏置值为2^(n-1) - 1。

        比如,2^10的E是10,所以保存为32位浮点数时,必须保存为10+127=137,即10001001。

3.3 浮点数取的过程

        指数E从内存中取出来,还可以再分为3种情况:

1.E不全为0或不全为1(常规情况):

        符号位S不用处理。

        指数E减去偏置值127(或1023),得到真实值。

        有效数字M的第一位加上原来舍去的1。

2.E全为0:

        这时,IEEE 754规定:

        指数E的真实值为1-127(或1-1023)。

        有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。

        这样做是为了表示±0,以及表示接近于0的很小的数字。

3.E全为1:

        这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位S)。

3.4 题目解析

        对于开头提到的代码,我们就进行一个解析:


完结        

        

        


网站公告

今日签到

点亮在社区的每一天
去签到