整形和浮点数的存储 4个月前

一、 整形在内存中的存储和整形提升


image

整数在内存中存储的是补码


那为什么在内存中偏要存储补码呢?

比如 (1-1)

image

这里我们要解释

补码可以将符号位和数值域统一处理 同时加法和减法也可以统一处理 (CPU只有加法处理器) 还有 补码和原码,原码和补码转化的方式是一样的(都是取反+1),不需要额外的电路

因此在内存中存储补码可以方便运算


简述一下整形提升

一、

//-1 的补码为
//11111111111111111111111111111111

char a = -1;
//因为 a 为 char 类型,所以只能存一个字节(8bit) 即为
//11111111

//又因为打印的方式为 %d 即为整形方式打印 所以要整形提升
//(因为为有符号类型,所以前面补1) 即为
// 11111111111111111111111111111111 (补码)
//转换为原码则为 10000000000000000000000000000001 (即为-1)


signed char b = -1;

//b为有符号字符类型,计算方式与a相同

unsigned char c = -1;
//11111111(存储内容)
//因为为无符号类型,且需要整形提升 所以前面补0 即为
//00000000000000000000000011111111

//因为其为无符号类型 所以原反补码相同
//即不需要转化.直接打印出来
//即为255
printf("%d %d %d",a,b,c); //-1 -1 255

有符号位的整形提升前面补1 无符号位的整形提升前面补0


二、

char a = -128;
//-128 的补码为 11111111111111111111111110000000
//所以在a中存储的为后8bit位即为
//10000000
//又因为要以无符号整形打印 所以要整形提升,又因为char为有符号类型所以补1
//11111111111111111111111110000000

//又因为数据要以 %u解读 即为无符号类型,即原反补相同,所以直接打印
//即为4294967168

printf("%u",a); //4294967168

char默认为 signed char 还是 unsigned char 并没有标准规定,取决于编译器 但 int 默认为 signed int short 默认为 signed short


二、 大小端存储的介绍

在整形存储方式中我们注意到

image

我们运算出的 内存存储数据 在内存是反着来的


大小字节端的内存处理方式

大端存储模式(大端字节序) : 数据的低位字节序保存在内存的高地址处,数据的高位字节序保存在内存的低地址处 . 小端存储模式(小端字节序) : 数据的高位字节序保存在内存的高地址处,数据的低位字节序保存在内存的低地址处

什么是低位字节序和高位字节序呢

我们举一个很简单的例子

int a = 0x11223344;

就以这个a为例子

在a中, 11 就是最高位字节序,44就为最低位字节序


写出一个程序,判断当前机器的字节序

int main()
{ 
  int a = 1; 
  //可以知道 a 的16进制补码为 00 00 00 01
  
  char *p = (char*) &a; 
  //取出a的地址并强制转换为char* 并将地址交付给 p
  //从而转换为存储a最低地址的一个字节即 01 或 00 
  
  //再进行判断
  if (*p == 1)
  {
    printf("小端"); //即低字节序存储在低地址处
  }
  else if(*p == 0)
  {
    printf("大端"); //即高字节序存储在低地址处
  }
}

三、 浮点型在内存中的存储

浮点数的存储为IEE 754规定,任意一个浮点数可以表示为下面的形式:

(-1) ^S * M * 2 ^E (-1) ^S 表示符号位, S == 0为正 , S == 1为负 M表示有效数字, 1 <= M < 2 2^E表示指数位

浮点数: 5.5 (十进制)
二进制: 101.1 --> 1.011 * 2^2 --> (-1)^0 * 1.011 * 2^2
                                S == 0   M = 1.011  E = 2

每个值该分配多少空间,IEE 754 也有规定

float:

image . . .

double:

image


关于M: 前面提到了M总是为1-2之间,因此M的表达式总是为 1.xxxxxxx 所以为了拥有更大的存储上限,IEE规定这个1可以省去 M内只存入小数点后几位


关于指数E: 首先,E是一个无符号整数 所以E为8位时,其取值范围为 0255 E为11位时,其取值范围为 02047

但是我们都知道指数在科学计数法中是可以为负数的 所以规定

存入内存时E的真实值必须加入一个中间数 8位时这个中间数为127 11位时这个中间数为1023


指数存入就是以上这些 指数取出就又可以分为三种情况了

情况 处理方式
E不为全0并且不为全1 对指数减去127得到真实值,再将有效数字M前加上一位1
E为全0 此时E的真实值即为 1-127 或 1-1023,有效数字M前不再加1,而是还原为 0.xxxxx的小数,这样做表示±0,以及接近于0的很小数字
E为全1 表示±无穷大(正负取决于S)

内存中怎么装这些东西?

float a = 5.5f;
//转化为二进制为 101.1

// (-1) ^0 * 1.011 * 2 ^2
// s === 0  M===011  E=2+127

// 0 10000001 01100000000000000000000
// 01000000101100000000000000000000
// 0100 0000 1011 0000 0000 0000 0000 0000
// 40 b0 00 00
// 以上十六进制数列即为内存中存放的数据

我们可以验证一下 image

image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2223057
累计阅读

热门教程文档

Spring Boot
24小节
C
14小节
Objective-C
29小节
Redis
14小节
Swift
54小节