整数和浮点数在内存中存储

简介: 整数的2进制表⽰⽅法有三种,即原码、反码和补码。

整数在内存中的存储

整数的2进制表⽰⽅法有三种,即原码、反码和补码。

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

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

大小端存储

⼤端(存储)模式:是指数据的低位字节内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存在内存的低地址处。

⼩端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存在内存的⾼地址处。

为何存在大小端?

大小端之分主要源于计算机系统中多字节数据的存储顺序问题。在计算机系统中,每个地址单元对应着一个字节,而一个字节为8位。然而,对于位数大于8位的处理器,如16位或32位的处理器,寄存器宽度大于一个字节,因此需要将多个字节进行排列。

#include <stdio.h>
  int check_sys()
{
    int i = 1;
    return (*(char *)&i);
}
  int main()
{
    int ret = check_sys();
    if(ret == 1)
{
    printf("⼩端\n");
}
 else
{
    printf("⼤端\n");
}
    return 0;
}

联合体:

int check_sys()
{
 {
  int i;
  char c;
  }un;
 un.i = 1;
 return un.c;
}

e294842160cf8aa22173e7e9f3a82c0e_550ddf8cec4e4e4889c1e5b0a8556cf7.jpeg

浮点数在内存中的存储

int main()
{
  int n = 9;
  float *pFloat = (float *)&n;
  printf("n的值为:%d\n",n);
  printf("*pFloat的值为:%f\n",*pFloat);
  *pFloat = 9.0;
  printf("num的值为:%d\n",n);
  printf("*pFloat的值为:%f\n",*pFloat);
  return 0;
}

在这个程序中,输出为9 0.000000 一个很大的数值 9.000000


任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

V = (-1) ^S*M*2^E

• (-1)^S 表⽰符号位,当S=0,V为正数;当S=1,V为负数

• M表⽰有效数字,M是⼤于等于1,⼩于2的

• E 表⽰指数位

在计算机内部保存M的时候,默认第一位总是1,所以可以舍去,只保留后面的部分。等到读取的时候,再把第⼀位的1加上去。这样做的⽬的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。


E为一个无符号整数,但是科学计数法中的E是可以出现负数的。等到读取的时候,再把第⼀位的1加上去。这样做的⽬的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。


指数E从内存中取出可以再分成三种情况:


E不全为0或不全为1:


指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第⼀位的1。


E全为0:


浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还

原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。


E全为1:


如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s)。

为什么 9 还原成浮点数,就成了 0.000000 ?

9以整型的形式存储在内存中,得到如下⼆进制序列:


1 0000 0000 0000 0000 0000 0000 0000 1001


最后23位的有效数字M=00000000000000000001001。

由于指数E全为0,所以符合E为全0的情况。因此,浮点数V就写成:

  V=(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146)

显然,V是⼀个很⼩的接近于0的正数,所以⽤⼗进制⼩数表示就是0.000000。


浮点数9.0,为什么整数打印是 1091567616?


⾸先,浮点数9.0等于⼆进制的1001.0,即换算成科学计数法是:1.001×2^3

所以:9.0 = (-1) *(1.001) ∗ 2^3。


那么,第⼀位的符号位S=0,有效数字M等于001后⾯再加20个0,凑满23位,指数E等于3+127=130,即10000010,

所以,写成⼆进制形式,应该是S+E+M,即0 10000010 001 0000 0000 0000 0000 0000

练习

signed char所有的最高位被当作符号位,剩下的为数值位。内存中存放的数据为补码。最前面为1,是负数。符号位不变,其他位置按位取反再+1。

unsigned char 0-255

3c6fa5e89c5b3a4d5747b67beffe0394_e9032379440c4ec9a8b649d3dd1352ec.png

这三种类型,在内存种存储时的补码是相同的,都是11111111。char类型要提升为int类型才能打印,整形提升的时候要补充符号位111111111111111,打印-1。signed char同理。unsigned0000000011111111,打印256。


打印的是无符号数。-128是1000000001000000%u打印认为a中存储的是无符号数,首先要整型提升。其在内存中的补码为1111 1111 1111 1111 1111 1111 111。打印的值是二进制补码所对应的十进制。128放入就不是128了,因为signed int所存储的值是-128~127。只能存8个比特位10000000。高位补1,1111111110000000。unsigned是无符号是但是用%d,又被当作无符号类型。


#include <stdio.h>
int main()
{
  char a[1000];
  int i;
  for(i=0; i<1000; i++)
  {
     a[i] = -1-i;
  }
  printf("%d",strlen(a));
  return 0;
}

求得的是字符串的长度,并且是\0(asc码值为0)之前的长度。

abd8879b1c6f7ef25bb5ac75382dadb8_ea6a648aeb0a478787cec5f0fc2f67c8.jpg

顺序为-1 -2 -3 ……-128 127 126 ……0。一共有255个数字。

#include <stdio.h>
int main()
{
  unsigned int i;
  for(i = 9; i >= 0; i--)
  {
     printf("%u\n",i);
   }
  return 0;
}

unsigned char只能存到255,取值范围为0-255。永远大于等于0,所以永远成立。

#include <stdio.h>
  int main()
{
  int a[4] = { 1, 2, 3, 4 };
  int *ptr1 = (int *)(&a + 1);
  int *ptr2 = (int *)((int)a + 1);
  printf("%x,%x", ptr1[-1], *ptr2);
  return 0;
}

相当于整型加整型。

4 20000000

相关文章
|
2天前
|
存储 小程序 编译器
数据在内存中的存储(探索内存的秘密)
数据在内存中的存储(探索内存的秘密)
9 0
|
4天前
|
存储 监控 NoSQL
Redis处理大量数据主要依赖于其内存存储结构、高效的数据结构和算法,以及一系列的优化策略
【5月更文挑战第15天】Redis处理大量数据依赖内存存储、高效数据结构和优化策略。选择合适的数据结构、利用批量操作减少网络开销、控制批量大小、使用Redis Cluster进行分布式存储、优化内存使用及监控调优是关键。通过这些方法,Redis能有效处理大量数据并保持高性能。
22 0
|
1天前
|
存储 算法 关系型数据库
实时计算 Flink版产品使用合集之在Flink Stream API中,可以在任务启动时初始化一些静态的参数并将其存储在内存中吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
15 4
|
4天前
|
存储 编译器 程序员
C语言:数据在内存中的存储
C语言:数据在内存中的存储
15 2
|
4天前
|
存储
浮点数在内存中的存储
浮点数在内存中的存储
25 0
|
4天前
|
存储
数据在内存中的存储之整数存储
数据在内存中的存储之整数存储
21 0
|
4天前
|
存储 C语言
C语言第二十九弹---浮点数在内存中的存储
C语言第二十九弹---浮点数在内存中的存储
|
4天前
|
存储 算法 编译器
整形和浮点型是如何在内存中的存储
整形和浮点型是如何在内存中的存储
|
4天前
|
存储 算法
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
【三种方法】求一个整数存储在内存中二进制中的1的个数附两道课外练习题
10 0
|
4天前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)