计算机底层对数据的存储(整形,浮点型)、大小端存储,以及整形提升和算数转换

目录

整形:

大小端存储

浮点数的存储

整形提升和算数转换:


编程中,各类计算机语言都对外提供了很多数据类型,那么在程序运行的过程中,数据在内存中是嗯么去进行存储的?

编程中的数据类型,以c语言为例,

整形:

        整形分四种,细分又分有符号和无符号两种类型

                有符号:存储的二进制最高位最为符号位(0代表正数,1代表负数);

                无符号:存储得时候不存在符号位;

//char在底层存储的时候存储的也是整形,在使用的时候会参照ANSII码值;c语言中占一个字节
char a = 1;
    signed char
    unsigned char;

//短整型,占2个字节
short a1 = 1;
    signed short
    unsigned short

//整形,占4个字节
int a2 = 1;
    signed int 
    unsigned int 

//长整形,占4个字节
long a3 = 1;
    signed long
    unsigned long

在对 a 进行赋值操作的时候,

1 是默认 int 整形,他的二进制数为 0000 0000 0000 0000 0000 0000 0000 0001

因为 a 是char类型的,在存储得时候只占一个字节,就是8个比特位,就会对这个 1 进行截取,所以这个 1 在存到 a 中的时候就变成了 0000 0001

相同的 1 在short中的存储就是 0000 0000 0000 0001

在存到 int 中的时候,就直接放进去

一样的道理,long在内存中也占4个字节。

整形在存储的时候,存储的都是这个数据的补码;说到这个补码,那就得说说原码,反码和补码之间的转换了:

//一个数的原码就是根据十进制和二进制的转换规则转换过来,

//正数的反码和补吗和原码一样,

//负数的反码就是其原码的符号位不变,将其他位逐一取反所得,
//负数的补吗就是将其反码加1;

//以整数10和-10举例说明

//正整数 10 

//原码 0000 0000 0000 0000 0000 0000 0000 1010
//反码 0000 0000 0000 0000 0000 0000 0000 1010
//补吗 0000 0000 0000 0000 0000 0000 0000 1010

//负整数-10

//原码 1000 0000 0000 0000 0000 0000 0000 1010
//反码 1111 1111 1111 1111 1111 1111 1111 0101
//补码 1111 1111 1111 1111 1111 1111 1111 0110

负整数的原码转换到补码:除符号位之外,取反 + 1即可,

从补码到原码:可以原路返回,-1 取反符号位之外的,另外还有一种方法,那就是 取反 + 1,就是从原码到补码的方式,同样也可以达到同样的效果。

以上就是有符号整形在内存中的存储了,

那么无符号整形,就好理解了,在存储的时候,全部的比特位用来存储数据,没有符号位,

举例

//因为无符号,所以原反补都一样

signed int a1 = 10

//存储的补码:0000 0000 0000 0000 0000 0000 0000 1010

unsigned int a2 = 10;

//存储的补码:0000 0000 0000 0000 0000 0000 0000 1010

//但是如果这样操作:

signed int a3 = -10;

//存储的补码:1111 1111 1111 1111 1111 1111 1111 0110

printf("%u\n",a3);//以无符号整形进行输出

//那么编译器会直接将a3在内存中的存储当成一个无符号整形,那也就没有符号位,将会是一个非常大的数字
//转换十六进制:输出结果就是0xff ff ff f6

大小端存储

另外一个点,那就是计算机的大小端存储,程序在运行过程中,数据在内存中的存储也分为大端字节序存储和小段字节序存储,这个和编译器没关系,是计算机本身对数据存储的一种决定方式。

大端字节序存储:指的就是数据的高位存储在内存低地址端,例如

//对于一个十六进制数 0x12345678,"12"是这个数据的高位,
//那假如说左边就是内存中的低地址的话,那么这个十六进制数在内存中的存储就是 0x12 34 56 78

小端字节序存储:指的就是数据的低位在内存中的低地址处

//对于一个十六进制数 0x12345678,"78"是这个数据的低位,
//那假如说左边就是内存中的低地址的话,那么这个十六进制数在内存中的存储就是 0x78 56 34 12

浮点数的存储

好了,说完整形在内存中的存储,就是浮点数在内存中的存储了

首先,要区分一下,整形是有分有符号数,和无符号数的,但是浮点数没有有符号和有符号之分。

接下来我们详细剖析:

//浮点数分为 float和double,
//其中float在存储得时候占4个字节32个比特位,double占8个字节64个比特位。

float a = 10.5f;

//这样一条语句,在底层存储的时候,要先将其转化为科学记数法将其表示

// 10.5, 其中,整数部分呢,比较好表示,10表示为十六进制就是 1010,那么这个0.5是怎么表示的。

//从二进制的权值表示不难推断:
//    0      0      0      0     .    0       0      0      0
//    2^3    2^2    2^1    2^0        2^-1    2^-2   2^-3   2^-4

//所以小数点后面的数字就需要一点一点去凑,比如0.5 就是0.1, 0.75就是0.11

//那我们就知道了10.5,用二进制表示出来就是 1010.1
//好了,现在把他换成科学记数法用来表示:1.0101*2^3
//但其实浮点数也有正负之分吗,那还需要进一步表示成:(-1)^0 * 1.0101 * 2^3

//好了到这里,我们就可以总结一下他的表达式:(-1)^S * M * 2^E
//对于S,他只需要0或者1,就可以完成对正负的表示,
//对于M,将所有的数字转换为这样子存储之后,M的第一位永远都是1,所以呢在进行存储的时候,可以对其进//    行省略,后序要对其进行操作的时候,在补上,这样就可以多出一位来存储数据了,
//对于E,他是一个无符号的整数,但是实际情况下,他也有负数的情况,为了应对这种情况呢,就要对其进行
//    矫正,如何矫正呢?在float类型32位字节存储的时候,会给E留出8个二进制位;在double类型64位字//    节存储的时候呢,会为其留出11位,所以规定,在进行E的存储的时候,会为其加上一个中间数,来让这//    个E扮演有符号的角色,float会为其加上中间数127,double则会为其加上中间数1023,用以矫正。

//用float进行存储的话,这32位怎么划分

float a = 10.5f;
//    0    0000 0000     0000 0000 0000 0000 0000 000
//    S        E                    M
//那么对10.5进行存储,S = 0; M = 3 + 127 = 0x1000 0010; M = 0101
//    0    1000 0010    0101 0000 0000 0000 0000 000
//    0100 0001 0010 1000 0000 0000 0000 0000 
//换算十六进制:0x41 28 00 00 如果是小端字节序的话那就是 0x00 00 28 41

//用double存储的话,64位怎么划分

double b = 10.5;
//0    0000 0000 000    0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
//S        E                M
//那么10.5进行存储:S = 0; M = 3 + 1023 = 0x1000 0000 010; M = 0101
//0    1000 0000 010    0101 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
//    0100 0000 0010 0101 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
//换算十六进制:0x41 25 00 00 00 00 00 00,小端存储就是0x00 00 00 00 00 00 25 41

整形提升和算数转换:

在从语言中,整型算术运算总是至少以缺省整型类型的精度来进行的,那就是int。当两个小于int整形的的操作数在计算机中进行计算时,计算机为了获得精度会先将两个类型在计算前先转换为int的整形,这个就叫做整形提升。

先看一个例子

#include <stdio.h>

int main(){
    char c = -10;
    
    printf("%u\n",c);

    return 0;
}

内存中存储的是-10,但是以无符号整形对其进行打印的时候,他还会是-10吗?

并不是,打印的结果是4294967286。这是为什么呢,咱们来分析一下

首先 -10放到char类型中,他存放的肯定是补码:咱们算一下

原码:1000 1010

反码:1111 0101

补码:1111 0110

那么在进行无符号打印的时候,这个-10就需要进行整形提升了,首先,在提升的时候,是不会有无符号这个概念的,所以要在其高位进行补齐,算数补齐补的是符号位,补完之后是这样的

1111 1111 1111 1111 1111 1111 1111 0110

现在呢在对其进行无符号整形打印,那就会视这段补码为无符号整形进行打印,那就不存在符号位,就直接当做正数进行输出,而这段二进制用计算机计算得到,他的十进制数就是4294967286。

当两个进度小于int的两个数进行算术运算的时候,就会进行整形提升,如果大于int精度的数进行算数运算的话,就要进行算数转换,意思就是先将精度低一些的数据转化为精度更高的那个数据的类型,然后进行运算,根据需要,在进行截断存储,那么精度高低是怎么划分的,

由高到底的顺序,精度也由高到低

long double

double

float

unsigned long

signed long

unsigned int

signed int

unsigned short

signed short

unsigned char

signed char

好了,今天的分享就到这里了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟婆的cappucino

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值