C语言中数据的存储

目录

数据的类型基本归类

整型在内存中的存储

原码、反码、补码

大小端介绍

signed char 和 unsigned char在内存中的取值范围

浮点型在内存中的存储


数据的类型基本归类

数据在内存中的存储类型大概有以下几种:

1、字符类型 char

2、整型 int

3、短整型 short

4、长整型 long

5、更长的整型 longlong

6、单精度浮点型 float

7、双精度浮点型 double

整型家族:

char(在内存中存储的形式是ASCLL码值,本质上是整型)

int

short

long

long long(C99中定义的)

其中也分有符号整型(signed)和无符号整型(unsigned)

对于int、short、long来说,加signed 前缀和没有前缀是一样的,也就是 signed int=int;

但是对于char来说不是这样的,char不加前缀的情况下具体是signed还是unsigned是取决于编译器的。

在定义一些没有负数概念的变量(如:身高体重)时,我们可以用unsigned,这样可以使数据较之signed多一位计数位。(unsigned没有符号位)

浮点型家族:

float(单精度,精度相对较低,存储的数据范围相对较小)

double(双精度,精度相对较高,存储的数据范围相对较大)

除了上面的基本类型,C语言中还规定了一些其他类型,如构造类型:

1、数组类型

2、结构体类型(struct)

3、枚举类型(enum)

4、联合类型(union)

其他的还有指针类型:

void *      int *        char *    double* .........

特殊的,还有空类型:

void表示空类型,通常表示函数的返回类型、参数、指针类型。

整型在内存中的存储

知道了基本的存储类型,那么数据在内存中又是怎么存储的呢?

先来看整型的存储方式。

在说明前先介绍原码、反码、补码。

原码、反码、补码

原码就是数据打印出来时的时候直接通过正负的形式写出的二进制序列

反码就是原码符号位不变,其他位按位取反所得到的

补码就是反码+1

正整数的原反补码是相同的。

负数则需要通过运算获得。

举个例子:

int a= -5;

它在内存中是怎么存储的呢?

首先,-5的原码是10000000000000000000000000000101

                  反码是111111111111111111111111111111111010

                  补码是111111111111111111111111111111111011

将其转化成十六进制显示(编译器显示内存存储的方式,便于观察)

                  a= -5 :  ff ff ff fb(4个二进制位转化成1个十六进制位)

我们来看一下 -5 在VS2022底下具体是怎么存储的:

 我们发现它存储的顺序和我们的是反的,这就涉及到大小端了。

大小端介绍

数据在内存中存储的时候,会涉及到大小端字节序的问题。

大小端也就是数据存入以及取出的方式。

大端存储:将数据的低位字节序的内容放在高地址处,将高位字节序的内容 放在低地址处。

如:

 大端存储就是将高位字节序(ff)放到低地址处,将低位字节序(fb)放到高地址处。

 

小端存储正好相反, 小端存储就是将高位字节序(ff)放到高地址处,将低位字节序(fb)放到低地址处。

总而言之,数据是如何放入内存的,就要怎么拿出来。

signed char 和 unsigned char在内存中的取值范围

先来看unsigned char,char在内存中只占一个字节(8个bit位),所以取值从00000000 ~ 11111111

 因为unsigned没有符号位,所以8个位都计数,取值范围0~255

signed char:

 00000000~01111111与unsigned char 是一样的。

但是符号位为1时变成负数,取值从-1~-128,所以signed char取值范围:-128~127

浮点型在内存中的存储

先看个例子:

 是不是与你预想的不太一样。怎么这里的Floatn和 n 就变了?

这是因为浮点数的存储方式和整型不一样,所以以浮点数的视角观察整型存储和用整型视角观察浮点数存储得到的结果是不同的。

下面具体介绍一下浮点数的存储方式。

这里就涉及IEEE754标准定义了:

 什么意思呢?浮点数可以表示为以下形式:

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

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

M 表示有效数字,M>=1且M<2

2^E 表示指数位

这也就是科学计数法。举个例子:

浮点数 3.5 按上述方式表示:

先把3.5以二进制形式表示:11.1( 2^1+2^0+2^(-1) )

此时,S=0,M=1.11,E=1        =(-1)^0 * 1.11 * 2^1

如果是3.14这种数字,转化为二进制时,小数点后无法完全精确得出0.14,只能无限接近,这就是为什么浮点数总是缺省精度的原因,而double比float精度高的原因就是它是64位,比float32位多了一倍,能有更多位存储,去逼近这个小数值

 

 

 可以看到,如果数据是以float类型存储的,内存中使用一个字节去保存S,8个字节保存E,剩余的23个字节保存M,并且这里的M因为必定>1,所以省去1,保留后面的位,最后取出时加上1就行了,这样就多一位存储数据,提高精度。而E在存储时,是按它的有效值+127进行存储的,比如E为-1,+127就是126,按126存储。

同样的,double里面也是一样的运作,只是比float多了32位,精度更高。同时这里E按照E+1023存储。

存储是这样的,取出时有三种情况:

1、E不为全0或全1:

S就是第一位的值,M加1,再补上小数点,float的话 E-127,double E-1023

比如内存中存的是 0 10000001 11000000000000000000000

S=0, E=100000001  (127+1-127=1)    M=11000000000000000000000 (1.11)

最后还原出来就是:(-1)^0 * 1.11 * 2^1

2、E全0:

此时还原E直接为-126,M不加1,写成0.00xxxxxxx的形式

因为E全0此时的值太小了,无限接近于0

3、E全1:

此时与E全0情况相反,值过大,接近于无穷,正负值取决于S。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值