深度解剖数据在内存中的存储

深度解剖数据在内存中的存储

  • 一、原码 反码 补码
  • 二、大小端介绍
    • 1、大端字节序存储:
    • 2、小端字节序存储:
    • 3、设计一个小程序,测试所使用的编译器是大端存储还是小端存储
  • 三、有符号char和无符号char在内存中存储的==区别==
    • 1、有符号char(signed char/ char)
    • 2、无符号char(unsigned char)
  • 四、浮点型在内存中的存储
    • 1、浮点数存储规则

一、原码 反码 补码

计算机能够处理的是二进制的数据,整形和浮点型数据在内存中也都是以二进制的形式进行存储的,整数在计算机内存中存储的是补码

正的整数:原码 反码 补码 相同

负的整数:原码 反码 补码需要各自进行计算

比如 -10:

10000000 00000000 00000000 00001010(原码)

11111111 11111111 11111111 11110101 (反码:原码每一位取反)

11111111 11111111 11111111 11110110 (补码:反码加一)
补码到原码是一样的操作
11111111 11111111 11111111 11110110 (补码)
11111111 11111111 11111111 11110111 (补码+1得到反码)
10000000 00000000 00000000 00001010(反码取反得到原码)

二、大小端介绍

1、大端字节序存储:

把一个数据的低字节处的数据存放在内存的高地址处,高字节处的数据存放在内存的低地址处。
例如:我用的vs2019就是小端字节序存储。

2、小端字节序存储:

把一个数据的低字节处的数据存放在内存的低地址处,高字节处的数据存放在内存的高地址处。

3、设计一个小程序,测试所使用的编译器是大端存储还是小端存储

如果你想要测试你所使用的编译器是大端存储还是小端存储可以用一段代码进行测试:

#include
int check_sys()
{
	int a = 1;//内存中存储是  01 00 00 00 或者  00 00 00 00 01
	return *(char*)&a;  //与下边的代码一样的意义但是简化了
	//char* p=(char*)&a;
	//if(*p==1)
	//return 1;
	//else
	//return 0;
}
int main() {
	if (1 == check_sys) {
		printf("小端\n");
	}
	else
		printf("大端\n");
	return 0;
}

三、有符号char和无符号char在内存中存储的区别

1、有符号char(signed char/ char)

范围 -128~127
一直+1
00000000 0
00000001 1
00000010 2

01111111 127
(之后为负数的补码,因为负数在计算机存储是补码来存储)
10000000 -128
10000001 -127

11111110 -2
11111111 -1
00000000 0
00000001 1
00000010 2

2、无符号char(unsigned char)

范围 0~255
一直+1
00000000 0
00000001 1
00000010 2

01111111 127
10000000 128
10000001 129

11111110 254
11111111 255
00000000 0
00000001 1
00000010 2

四、浮点型在内存中的存储

1、浮点数存储规则

根据国际标准IEEE,任何一个二进制浮点数V可以表示成下面的形式:

V =(-1) ^S M2 ^E

(-1)^S表示符号位当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于等于2。
2^E表示指数位。

例如:
10进制的:5.5 = 2进制的:101.1
(-1) ^01.012 ^2
s=0
M=1.01
E=2
如下是规定的存储规则:
对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
深度解剖数据在内存中的存储_第1张图片
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
深度解剖数据在内存中的存储_第2张图片
对于M来说:
IEEE 754规定, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
对于E来说:
至于指数E,情况就比较复杂。首先,E为一个无符号整数(unsigned int)这意味着,如果E为8位,它的取值范围为0 ~255;如果E为11位,它的取值范围为0 ~2047。
但是,我们知道,科学计数法中的E是可以出
现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
但是E还有两种特殊情况:
E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于
0的很小的数字。
E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)。

那么所举的例子十进制的5.5 在内存中为
0 10000001 0100000000000000000000000000000000

如果感觉对你有所帮助,不如留下一键三连,万分感谢!!!

你可能感兴趣的:(c语言,算法)