c语言中数据的存储

C目录

c语言中数据的类型及其基本归类

整型在内存中的存储

大小端介绍

char类型在内存中的存储

存储方式

整形提升

浮点型在内存中的存储

存储方式

E和M的特殊规定


c语言中数据的类型及其基本归类

c语言中内置数据类型以及该类型的每一个数据所占内存主要有以下几种:
· char                   占一个字节

· short                  占两个字节

· int                      占四个字节

· long                   占四个字节

· long long           占八个字节

· float                   占四个字节

· double               占八个字节

此外,还有其他的数据类型,比如结构体类型,指针类型,空类型,这里不过多赘述。

可以把数据类型归类为以下几种:

1.整形:

char

    signed char

    unsigned char

short

    signed short

    unsigned short

int

    signed int

    unsigne int

long  

    signed long

    unsigned long

2.浮点型

float

double

3.构造类型

数组

结构体 struct

枚举    enum

联合    union

4.指针类型

5.空类型

整型在内存中的存储

在了解整形在内存中的存储之前,要先知道原码,反码,补码的概念,即整形数值以二进制形式存储,对于整形数据来说,都是以补码的形式存放在内存中。

对于原码、反码、补码而言,都有“有符号”和“无符号”两种。

“有符号”是指二进制数据从左往右第一位,如果是“0”,那么这个二进制数据表示正数,如果是“1”,那么这个二进制数据表示负数。

“无符号”是指没有正负之分,全部是正数,这样可以存范围更大的数值。(比如有符号位int类型,可以存 -2^31——2^31-1 范围内,而无符号int类型可以存0——2^32)

原码:数值翻译成二进制后得到的就是原码。

反码:原码的符号位不变,其他位取反。

补码:反码加1得到补码。

(正数的原码、补码、反码相同)

比如下面:

然后在VS2019里面设计一个int类型变量,初始化值位-10,找到对应的内存存储,发现如下:
 

 其顺序和补码按高位字节到低位字节不同,所以这里又要引入大小端的概念。

大小端介绍

大端存储模式:指数值的低位字节存储在内存的高地址中,高位字节存储在内存的低地址中。

  

小端存储模式:指数值的低位字节存储在内存的低地址中,高位字节存储在内存的高地址中。

低位字节和高位字节:

比如int类型-10的补码:11111111111111111111111111110110

在四个字节中存储,分为 11111111  11111111  11111111  11110110

四个比特位一组,十六进制,所以是 ff ff ff f6  ,这样子左边是高位字节,右边是低位字节。

内存的高地址和低地址:

如上图,在内存图右边的0x007DE841到0x007DE845就是从低地址到高地址。

char类型在内存中的存储

存储方式

定义 char a=-10;由于char类型只有一个字节,所以只有八个比特位的位置存放。

它在内存中存储是:11110110

得到的方式如下:

-10的原码:100000000000000000000000000001010

-10的反码:1111111111111111111111111111111110101

-10的补码:1111111111111111111111111111111110110

int类型的-10的补码取后八位得到的结果就是char类型的存储结果

整形提升

使用char类型的数据的时候,要把它存储的八个二进制位整形提升,有符号位的char类型,从左往右第一位是符号位,符号位后面补齐的数字和符号位相同;无符号位的,前面全部补0。

比如char(默认signed)类型的1110110   第一个“1”就是符号位,于是1后面补24个“1”,得到最后的结果是1111111111111111111111111111111110110,

而如果是unsigned char类型存储的1110110,那么无符号位,则最后结果是:
0000000000000000000000001110110

转化成原码有两种方式,一个是先减“1”,再除符号位以外按位取反;另一个是先除符号位外按位取反,再加上“1”。

此外,由于char类型只有一个字节,即八个比特位,所以有符号位只能存-128——127的数据,超过则无法存储,如下图。

顺时针是+1操作,当01111111(十进制127)+1后,到了10000000,由于是补码的方式存下来,

10000000整形提升后变换得到的原码是1000000000000000000010000000,所以是-128,然后不断+1到了11111111,实际上是-1,这个时候+1就到了0。所以char类型存储是这样循环的,可以以下面一个例子看出:

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

运行结果是255,而不是1000,是因为它a[i]是这样子的:

-1,-2,-3,-4,-5,……,-127,-128,127,126,……,3,2,1,0,-1,-2………………

对于strlen,读到“\0”或者ASCll码是0的时候就会停下来,所以从-1读到0就会停下。而这里面有-1到-128是128个,127到1是127个,所以127+128=255,结果是255。

浮点型在内存中的存储

存储方式

根据国际标准 IEEE (电气和电子工程协会)  ,任意一个二进制浮点数 V 可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^s 表示符号位,当 s=0 , V 为正数;当 s=1 , V 为负数。
M 表示有效数字,大于等于 1 ,小于 2 。
2^E 表示指数位
 

对于32位(float类型单精度浮点数)的浮点数,存储模型是,符号位S占一个比特位,指数位E占八个比特位,有效数字M占23个比特位。而对于64位(double类型双精度浮点数)的浮点数,存储模型是,S占1个比特位,E占11个比特位,M占52个比特位。下图是32位浮点数存储模型图:

定义 float a=10.5;换算成二进制是1010.1

这个数是正数,所以S=0,由于二进制是1010.1,所以M是1.0101,指数位应该是3。(指数位可以类比十进制10^E,因为这里是二进制,所以是2^E,效果都是小数位移动。)

所以写成 (-1)^0*1.0101*2^3

但是写进内存是01000001001010000000000000000000

分区来看,0  10000010  01010000000000000000000

但是发现指数位E和有效数字M和我们想的不一样,这是因为IEEE对其有特殊规定。

E和M的特殊规定

E的特殊规定:

首先,E是一个无符号整数,所以八位的E取值范围位0~255;11位的E取值范围位0~2047。但是指数E是可以取负的,所以对于八位的E,初始的E要加上中间数127,得到的才是存进内存的E的数值;对于11位的E,这个中间数是1023。

所以上面的真实E是3+127=130.

比如0.5,换算成二进制是0.1,但是规定M要是1<=M<2,所以0.1=1*2^-1(二进制),这个时候E就是-1,存进内存的E就是-1+127=126.

M的特殊规定:

由于M是一个1~2之间的数,所以M总是1.xxxxxxx的形式,这个时候小数点左边的1是恒定的,所以可以把它省略,在取出这个浮点数的时候,再把这个“1”加上去就可以了,这样就可以空出一个比特位来存有效数字。

然后,E从内存中取出还分为三种情况:

E不全为0或者全为1:

这个时候,把E减去127得到后的E,然后M左边加上1,M原本的是小数点后面的内容。

比如0.5,二进制存储0 01111110 00000000000000000000000

取出来就是S=0,E=126-127=-1,M=1.00000000000000000000000,得到的结果是

(-1)^0*1*2^(-1),是0.1,换算成十进制是0.5。

E全为0:

此时,E存储结果全是0,只有原本值是-127,才会得到E=-127+127=0,所以结果是

1.xxxxx /(2^127),再化一下就是0.1xxxxx/(2^126),是一个非常非常小的数字,就是0.

E全为1:

这时,如果有效数字全为0,那么表示+-无穷大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力努力再努力.xx

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

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

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

打赏作者

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

抵扣说明:

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

余额充值