✨✨大家好,我是青衫,这一期的主要内容是关于剖析数据在内存中的存储。✨✨
✨✨知识点✨✨ 数据类型 原码、反码、补码 大小端存储 浮点数的存储
正文:
在前面,我们已经学习了基本的内置类型,一共分为七种:
char | 字符数据类型 |
---|---|
short | 短整型 |
int | 整形 |
long | 长整形 |
long long | 更长的整形 |
float | 单精度浮点型 |
double | 双精度浮点型 |
按照数据类型归类的话,还能分成:整形家族、浮点型家族、构造类型、空类型、指针类型。下面我们来逐一介绍。
char | |
---|---|
unsigned char | |
signed char | |
short | |
unsigned short | |
signed short | |
int | |
unsigned int | |
signed int | |
long | |
unsigned long | |
signed long |
每一个类型又分为有符号和无符号。那么没写有符号还是无符号的时候是什么类型呢?
这个视编译器决定。像vs中 int 类型代表的是有符号类型。
相信有很多人看到char类型会有疑问:chat不是字符类型吗? 没错,但是其原理是:字符会转化为相应的ASCII码值来存储,所以严格来说,char是算在整形家族里面的。
🎈整形的存储形式 🪂分为:原码、反码、补码 计算机中有符号数的表示方法有三种,即原码、反码、补码。 三种符号均分为两部分:符号位和数值位。符号位都是用 ‘0’ 来表示 ‘正’,‘1’ 来表示 ‘负’。而数值位,三种表示方法各不同。 原码 直接将二进制按照正负数的形式翻译成二进制就可以。 反码 将原码的符号位不变,其他位依次按位取反就可以得到了。 补码 反码 +1 就得到补码。 正数的原码、反码、补码是相同的,而负数的则不同。 例:-1存储在整形中的原码、反码、补码
对于整形来说:数据存放内存中其实存放的是补码。
🪂大小端存储:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
例如:一个数据 0x 11 22 33 44
那么,我们如何判断我们的电脑是大端还是小端存储呢?
#include <stdio.h>
int main()
{
int a = 1;
int ret = *(char*)&a;
if (1 == ret)
{
printf("小端\n");
}
else
{
printf("大段\n");
}
return 0;
}
🎈关于正反补码的一些练习 🎄1、
答案: -1 -1 255 解析: char 和signed char都是有符号的字符类型,是有符号位的,最后一位作为符号位。
作为%d打印时会发生整形提升,最后得到-1。 而unsigned char 是没有符号位的,最后一位仍然充当数字位。并且都是正数。
所以这里就已经就结束了,得到的就是255。因为正数的补码就是原码。 🎄2、
答案: 4,294,967,168 解析: 如图,因为是有符号的,所以最后一位是作为符号位的,一直是负数,所以是1。
得到最终结果,很多人会有疑问,不用变成原码吗?但是我们是%u形式打印的,是作为无符号的整形打印,也就是说把这段作为正数打印,没有符号。
放入计算器中计算我们也可以验证这一点。 🎄3、
答案:4,294,967,168 解析:
🎄4、
答案:-10 没什么好说的,整形相加,最后打印也是整形格式,所以正常算就可以了。 🎄5、
答案:死循环 解析:因为i是无符号类型的,所以不可能小于0的。故而无法退出循环。 🎄6、
答案:255 解析:因为strlen碰到 0 或者 \0 会停止,而char类型的范围是-128-127,所以当-1-128的时候就会变成127,然后继续执行127次。128+127总共执行255次。 🎄7、
答案: 死循环 解析:因为unsigned char 类型的范围是0-255,所以一直小于等于255,退不出循环。 最后,附上一张char的二进制范围图,方便记忆
类型 🎄浮点数包括:float、double、long double 根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式: 🎄(-1) ^ S * M * 2 ^ E (这里不是异或的意思,是次方的意思) 🎄(-1) ^ S表示的是符号位,当S=0,V为正数;当S=1,V为负数。 🎄M表示有效数字,大于等于1,小于2。 🎄2^E表示指数位。(因为二进制是乘除2的) 例如: 十进制的 5.0 表示成二进制就是 101.0,又可以转化为 1.01*2^2。 所以S=0,M=1.01,E=2。
二进制表示: 单精度浮点数的表示
双精度浮点数的表示
另外,对于E和M还有一些特殊的规定: 🎄 因为存储M的时候,第一位总是1的,所以1是不存储的,只存储的是后面小数部分,读取的时候再把1加上。 🎄 E是一个无符号整数,如果 E是8 个bit,那么存储范围就是0-255;如果是11个bit,那么存储范围就是0-2047。当E是负数时,我们必须确保他是非负的,所以得加上一个中间数,8位的就是加上127;11位的就是加上1023。 E从内存中取出还要分成三种情况: 🎄 E不全为0或不全为1:E存在内存中的值有0有1的话,取出来的时候正常减去之前加上的-127。 🎄 E全为0:这时候E原来的值就是1-127(或者1-1023),说明原来是一个数乘上无限接近0的数字,所以M还原的时候不需要+1了,这样做是为了表示+-0,以及很接近0的数字。 🎄 E全为1:这时候是为了表示无穷大的。
结果:9 0.000000 1,091,567,616 9.000000 解析: 第一个是9没问题。 第二个因为是作为浮点数打印的,而整形9的二进制代码是
E是全为0的,我们能知道,这是表示0的 第三个,是把他设置成浮点数的类型,但是按照整形形式打印
这里的S=0。E=3+127,就是10000010,而M=1.001,存进去的时候去掉1,存001,后面补0。 但是按照整形计算出来的数字就是 1,091,567,616 了。 第四个浮点数的形式存储,按照浮点数形式打印,所以打印出来是9.000000。