剖析数据在内存中的存储(包括int double类型,原码,反码,补码和电脑大小端存储的详细解释)

66 阅读4分钟

整形在内存中的存储

整形家族非常庞大,有以下几种类型 大小(单位是字节) 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.