数据在内存中的存储

在说明数据在内存的存储前,先给大家介绍下大小端。

大小端

那么什么是大小端呢?

其实超过一个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分
为大端字节序存储和小端字节序存储,下面是具体的概念:
大端(存储)模式:是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存
在内存的低地址处。
小端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存
在内存的高地址处。

下面以图片进行更直观的描述

 

在搞懂什么是大小端之后。我们来思考一下为什么会有大小端呢?

这是因为在计算机系统中,存储是以字节为单位的,每个地址单元都对应一个字节,一个字节为8bit。在C语言中char 8bit,short 16bit,long 32bit(编译器不同会不同),所以必然存在一个如何将多字节安排的问题,这就导致了大端存储模式和小端存储模式。

int judge()//判断当前环境下是大端字节序还是小端字节序

{

        int a = 1;

        return *(char*)&a;

}

int main()

{

        if (judge() == 1)

                printf("小端");

        else

                printf("大端");

        return 0;

}

整数在内存中的存储

我们知道整数的二进制表示方法有三种:原码,反码,补码

三种表示方法均有符号位和数值位(针对有符号数),最高位为‘0’表示‘正’,为‘1’表示‘负’,其余为数值位。

正整数原码,反码,补码相同。

负整数:

原码:将数值按照正负数的形式编译成二进制;

反码:将原码除符号位的其他位取反得到;

补码:反码+1得到

在数据存储在计算机里的就是补码

在明白大小端和整数在内存中的存储后,我们来看看下面一段代码

int main()
{
    char a = -1;
    signed char b = -1;
    unsigned char c = -1;
    printf("%d %d %d", a, b, c);

}

这里的结果是-1,-1, 255。

由前面讲过的整数在内存中的存储,可以先把-1转化成三码

原码:10000000000000000000000000000001

反码:  1111111111111111111111111111111111110 

补码:1111111111111111111111111111111111111

但是因为char的字节是8bit,所以只能把补码的候8位存入a,b,c。(11111111)

这里会涉及到一个整形提升的概念:

1.有符号整数提升是按照变量的数据类型的符号位来决定的

2.无符号整数提升,高位补0

所以可以知道 a和 b(有符号)中存入11111111111111111111111111111111(补码)->

10000000000000000000000000000000(反码)->1000000000000000000000000001(原码)

所以可以知道以%d形式输出a和b是-1

c(无符号)中存入00000000000000000000000011111111(补码)(反码)(原码),则c输出255

 

浮点数在内存中的存储

举一个浮点数例子5.5。表示除它的二进制数,我们知道整数二进制从右到左权重分别是2^0,2^1,2^2……可以推出小数点右边权重从左到右权重依次为2^-1,2^-2……所以5.5可以表示成101.1。那么如果是-5.5该如何表示呢?

根据国际标准IEEE754,任意一个二进制浮点数V可以表示成下面的形式:

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

(-1)^s表示符号位,s=0为正,s=1为负

M表示有效数字,范围是(1,2)

2^E表示指数位

也就是说5.5可以写成1.011*2^2(s=0,M=1.011,E=2),-5.5写成-1.011*2^2。

IEEE754规定

对于32位的浮点数,第一位是S,接下来八位是M,剩下的是E

64位浮点数同理如图所示 

 

但是并不是所有的浮点数都能精确的用二进制表示的如5.14,这就存在浮点数精度缺失问题,具体介绍看我之前写的《浮点数计算精度问题》 

前面说M范围是(1,2),可以写成1.XXXX存储在23位中(32位浮点数),所以为了更精确,常常会把1给舍去,将XXXX存入,这样就精确了一位。

对于指数E(无符号整数)

E的范围是0~255,但是实际上是存在负数指数的,所以IEEE754 规定E存入内存时必须加上一个中间值,8位E加127,11位加1023

了解了浮点数的存储后,我们来讲讲浮点数的取数过程

1.E不全为0并且不全为1

E的计算值减去127得到真实值,有效数字M前补上1

比如0.5   1.0*2^-1,所以M为1.0补上舍去的1变为0,用23位补齐,E为-1,+127变为126(01111110),因为是整数所以s为0.所以0.5的二进制表示为

0 01111110 000000000000000000000

2.E全为0 

真实值等于1-127=-126。一个数1.XXX乘以2^-126非常小,是一个接近于0的数。

3.E全为1

这是如果M全为0,则这个数表示为一个正负无穷大的数

  • 67
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值