C语言-数据的存储

数据类型

类型的基本归类

在这里插入图片描述
意义

  1. 确定类型开辟内存空间的大小(大小决定了使用范围)。
  2. 如何看待内存空间的视角。

整形在内存中的存储 limit.h

原码

最高位为符号位,0代表正数,1代表负数,非符号位为该数字绝对值的二进制表示。

如:

127的原码为0111 1111
-127的原码为1111 1111

反码

正数的反码与原码一致;

负数的反码是对原码按位取反,只是最高位(符号位)不变。

如:

127的反码为0111 1111
-127的反码为1000 0000

补码

正数的补码与原码一致;

负数的补码是该数的反码加1。

如:

127的补码为0111 1111
-127的补码为1000 0001

正数的原、反、补码都相同。

对于整形来说:数据存放内存中其实存放的是补码。

使用补码的主要原因

使用补码的主要原因是可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。计算机中乘除法都是用加减法组和而成的(移位运算除外),简化了加减运算就能简化整体的运算。

在这里插入图片描述

大端存储与小端存储

大端(存储)模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

小端(存储)模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

在这里插入图片描述

存在大小端的原因
  1. 一开始是由于不同架构的CPU处理多个字节数据的顺序不一样,比如x86的是小段模式,KEIL C51是大端模式。但是后来互联网流行,TCP/IP协议规定为大端模式,为了跨平台通信,还专门出了网络字节序和主机字节序之间的转换接口(ntohs、htons、ntohl、htonl)

  2. 大小端模式各有优势:小端模式强制转换类型时不需要调整字节内容,直接截取低字节即可;大端模式由于符号位为第一个字节,很方便判断正负。

应用场景:
  1. 不同端模式的处理器进行数据传递时必须要考虑端模式的不同.

  2. 在网络上传输数据时,由于数据传输的两端对应不同的硬件平台,采用的存储字节顺序可能不一致。所以在TCP/IP协议规定了在网络上必须采用网络字节顺序,也就是大端模式。对于char型数据只占一个字节,无所谓大端和小端。而对于非char类型数据,必须在数据发送到网络上之前将其转换成大端模式。接收网络数据时按符合接受主机的环境接收。

在这里插入图片描述

浮点型在内存中的存储 float.h - float、double、long double 类型

存入

任意一个二进制浮点数可以表示为:

在这里插入图片描述

对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

在这里插入图片描述

对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

在这里插入图片描述

对有效数字M的特别规定

  1. 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形
    式,其中xxxxxx表示小数部分。

  2. 在计算机内部保存M时,默认这个数的第一位总是1,被舍去,只保存后面的小数点后xxxxxx部分。

对有效数字E的特别规定

E为一个无符号整数(unsigned int) ,
若E为8位,它的取值范围为0 ~ 255 ;
若E为11位,它的取值范围为0~2047。
但是科学计数法中的E是可以出现负数的,
所以存入内存时E的真实值必须再加上一个中间数,
对于8位的E,这个中间数是127;
对于11位的E,这个中间数是1023。

比如
2^2的E是2,保存成32位浮点数时,保存成2+127=129,即10000001。

float f = 5.5;
//5.5
//101.1
//(-1)^0 * 1.011*2^2
//(-1)^s * M     * 2^E
//S = 0
//M = 1.011 
//E = 2
//2+127=129 - 10000001
//0 10000001 01100000000000000000000
//0100 0000 1011 0000 0000 0000 0000 0000
//0x40b00000
//(-1)^0 * 1.011 * 2^2

取出

然后,指数E从内存中取出还可以再分成三种情况:

E不全为0或不全为1

这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

比如:

//0.5(1/2)
//0.1 二进制表示形式
//(-1)^0 * 1.0 * 2^-1
//S = 0
//M = 1.0  去掉整数部分为0,补齐0到23位 00000000000000000000000
//E = -1
//E + 127【中间值】 = 126 -01111110
0 01111110 00000000000000000000000

E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

//0 00000000 01100000000000000000000
//+/- 0.011 * 2^-126
//正负无穷小

E全为1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

//0 11111111 01100000000000000000000
//E+127 = 255
//E = 128
//1.xxx * 2^128
//表示的正负无穷大的数字

例子

int main()
{
	int n = 9;
	//0 00000000 00000000000000000001001-补码
    //S    E              M
    //(-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146)
	
	float *pFloat = (float *)&n;
	printf("n的值为:%d\n", n);//9
	printf("*pFloat的值为:%f\n", *pFloat);//0.000000
	//(-1)^0 * 0.00000000000000000001001 * 2^-126

	*pFloat = 9.0;
	//1001.0
	//1.001*2^3
	//(-1)^0 *1.001 * 2^3
	//01000001000100000000000000000000 -1091567616 

	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);//9.0
    return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

eeenkidu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值