整形在内存中的存储
整形家族非常庞大,有以下几种类型 大小(单位是字节) char 1 short 2 int 4 long 4 long long 8 而这些类型又分为有符号的(signed),也就是有正负之分 无符号的(unsigned).由于整型各个类型存储类似,这里我用int类型来讲解
原码,反码和补码
二进制我相信大家应该都是多少了解一点的.而原码,反码和补码就是二进制的精髓. 补码是数据存储在内存中的形式 三种表示方法均有符号位和数值位,第一位是符号位,' 0 '表示正,'1'表示负.,其余为数值位. 正数的原码,反码和补码相同
原码
数值按照正负数的形式翻译成二进制就可以得到原码
//原码
int a = 10;
//00000000 00000000 00000000 00001010 --a
int b = -10;
//10000000 00000000 00000000 00001010 --b
反码
原码符号位不变,其他位按位取反得到反码
//反码
int a = 10;
//00000000 00000000 00000000 00001010 --a
int b = -10;
//11111111 11111111 11111111 11110101 --b
补码
反码+1就得到补码
//补码
int a = 10;
//00000000 00000000 00000000 00001010 --a
int b = -10;
//11111111 11111111 11111111 11110110 --b
大小端存储
为什么会有大小端存储
我们找到计算机存储是以字节为单位的,而int等类型大小为四个字节.所以就必定会在存放方式存在分歧.
我们的电脑的地址有高地址和低地址之分.这个是为了区分在哪一端.
大端(存储)模式,数据的高位放在低地址处,数据的低位放在高地址处
小端(存储)模式,与大端模式相反.
数据的高位放在高地址处,数据的低位放在低地址处
写代码来验证当前机器的存储模式
vs2022下
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Check()
{
int i = 0;
return *(char*)(&i);
}
int main()
{
int ret = Check();
if (ret == 1)
{
printf("大端\n");
}
else if(ret==0)
{
printf("小端");
}
return 0;
}
(char)(&i);
这个代码的意思是取出i的地址,类型是int ,然后强制转换成char*,char进行解引用只能访问一个字节,而我们在刚开始把i初始化为1.
我们可以根据它取出来的数字是否为1来判断.
如果是1,char是在低地址到高地址进行访问的,所以int存储的第一位是1,即为小端存储
浮点数在内存中的存储
首先我们先分析一下上面的代码: 我把n的地址取出来,将int类型强制转化为double 并赋给ptr,再把ptr解引用打印出来.我们可以得出来应该结论
浮点数的存储和整型的存储完全不同.
根据国际标准,任意一个二进制浮点数V可以表示成下面的形式:
v = (-1)^S * M * 2^E
其中(-1)^S表示符号位,当S=0,V为正;当S=1,V为负。
M表示有效数字,大于等于1,小于2。
2^E表示指数位
举例
十进制: 5.5
二进制: 101.1 相当于1.0112^2*
5.5>0 ---> S=0;
M>=1 && M< 2 ---> M=1.011;
E=2;
对于32位的浮点数来说,第一位是符号位S,然后有8个指数位E,剩下23个数值位M
特别的:因为我们的指数有正负之分,如果E的大小为8比特位,大小就是0-255.
我们要在中间插入一个数127,作为正负的分界.
比如5.5 ,E=2;所以当它保存到内存中时,它的值会变为127+2=129 ,也就是1000 0001.