004 数据在内存中的存储形式——“C”

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、类型归类
  • 二、原码反码补码是什么
  •        原码反码补码的转换形式
    • 1.大端小端节序存储
    • 2.浮点数在内存中的存储形式

一、类型归类

整形家族

char 1个字节 8bit

int 4个字节 32bit

short 2个字节 16bit

long 4个字节 32bit

char

 unsigned char  

 signed char 

short

unsigned short ·

signed short

int 

unsigned int

signed int

long

unsigned long

 signed long

unsigned 表示只能是整数即无符号整数

signed 表示正负皆可以

自定义类型:
数组类型  结构体类型 struct  枚举类型 enum  联合类型union

指针类型

int*  char*  float*  void*空类型

void表示空类型

通常应用于函数的返回类型,函数的参数,指针类型

二、原码反码补码是什么

原码反码补码是二进制三种表现形式

最高位表示符号位  其余是数值位

原码用于打印数值,计算

补码存储在计算机内

符号位用0表示正,用1表示负

as:-5  5

10000000 00000000 00000000 00000101     -2^1+2^0=-5

00000000 00000000 00000000 00000101     2^1+2^0=5

原码反码补码的转换

原码——>补码

 原码10000000 00000000 00000000 00000101

 反码111111111 111111111 111111111 111111010  符号位不变,按位取反

 补码111111111 111111111 111111111 111111011  +1

 第一种方法:补码——>原码   -1取反 

111111111 111111111 111111111 111111011

111111111 111111111 111111111 111111010    -1

10000000 00000000 00000000 00000101    取反

第二种方法:补码——>原码    取反+1

111111111 111111111 111111111 111111011  

10000000 00000000 00000000 00000100   取反

10000000 00000000 00000000 00000101   +1

在此基础上我们可以扩展一下关于char类型的取值范围

char =1byte字节=8bit

signed有符号的char的取值范围是-128到127

00000001  2^0   1

00000010    2^0   2

00000011  2^1+2^0   3

00000100  2^2    4

00000101   2^2+2^0    5

....

01111111       127

10000000     -128

10000001     -127

...

11111111补码       11111110减1  10000001按位取反  ——>-1

无符号的char的取值范围是0到255

00000001  1

00000010  2

00000011  3

00000101  4

00000110  5

...

01111111  127

10000000   128  无正负之分

10000001    129

11111111     255

三、大端小端字节序存储

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元 都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short 型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32 位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因 此就导致了大端存储模式和小端存储模式。

1.大端字节序存储:把一个数据的低位字节的数据,存放在高地址处,把高位字节的数据存放在低地址处

2.小端字节序存储:把一个数据的低位字节的数据,存放在低地址处,把高位字节的数据存放在高地址处

 四.国际标准IEEE

1、二进制浮点数的表示形式:

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:

(-1)^S * M * 2^E         其中E表示小数点向左移动的位数

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

as:-5

101.0=(-1)^1*1.01*2^2

M=1.01

S=1

E=2

as:5.5

101.1=(-1)^0*1.011*2^2

M=1.001

S=0

E=2

 0.5的二进制形式为0.1   0.25的二进制形式为0.01  0.125的二进制形式为0.001依次类推

因此浮点数在内存中的存储不一定精确

IEEE 754对有效数字M和指数E,还有一些特别规定。 前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。 IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的 xxxxxx部分。比如保存1.01的时 候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位 浮点数为例,留给M只有23位, 将第一位的1舍去以后,等于可以保存24位有效数字。

2.把指数从内存中取出的三种形式

(-1)^S*M*2^E   

1.E全为0

放在内存内竟然是全0,这可是+127   那之前的数字可是+-  1.xxxx*2^-127 一个无限接近于0的数字

还原的时候: 浮点数的指数E等于1-127(或者1-1023)即为真实值

真实值有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。

2.E全为1

有效数字M全为0,表示正负无穷大(正负取决于符号位)

八个比特位   11111111  ——>E=255还原的时候   真实值至少为255-127

3.E不全为0也不为全1

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

int main()
{
	float f = 5.5f;
	//101.1
	//(-1)^0 * 1.011 * 2^2
	//0 10000001(129-127=2(真实值)) 011000000000000000000000(把1放置在前面,这样做可以保存24位有效数字,更加精确)
	//
	return 0;
}


int main()
{
	int n = 9;
	float* pfloat = (float*)&n;    //指针的类型,以什么样的权限什么样的视角解读,认为float*指针认为内存中的二进制序列是浮点数二进制序列
	printf("n的值为:%d\n", n);
	printf("*pfloat的值为:%f\n", *pfloat);
	*pfloat = 9.0;   //以浮点数的视角,采用浮点型的数字
	printf("num的值为:%d\n", n);   //1091567616
	printf("*pfloat的值为:%f\n", *pfloat);   
	return 0;
}

第一:n=9  用pfloat的指针接收n的地址,*pfloat解引用取出n的值,n==*pfloat,%d解读与用%f解读为何差距如此之大

第二:赋*pfloat==n一个值9.0,用%d解读与%f解读为何差距如此之大

int main()
{
	int n = 9;
//	//00000000  00000000 00000000 00001001
//	//0 E:00000000 M:000000000000000001001
//  //E为全零,真实值不用再在前面加上1了,直接还原成0.xxxxx的小数,实在太小了
//	//真实值E=1-127=-126 
//	//M=0.000000000000000001001
//	//(-1)^0*0.0000000000000000000001001*2^-126
//	//以%f打印只能打印小数点后六位
	float* pfloat = (float*)&n; //指针的类型,决定以什么样的权限什么样的视角解读,认为float*指针认为内存中的二进制序列是浮点数二进制序列
//(-1)^0* 0. 000000000000000001001*2^-126=0.000000 float类型读取小数点后六位
	printf("n的值为:%d\n", n);   ——>9
	printf("*pfloat的值为:%f\n", *pfloat);     ——>0.000000
	*pfloat = 9.0;   //以浮点数的视角,采用浮点型的数字
//	//1001.0
//	//1.001*2^3
//	//(-1)^0*1.001*2^3
//	//S=0
//	//E=3
//	//M=1.001
//	//0 10000010  00100000000000000000000
// 01000001000100000000000000000000  正数的原反补相同
//   真实值E:130-127=3  补1——> 1.001   
	printf("num的值为:%d\n", n);   //1091567616
// %d最高位为0,原码反码补码相同,
// 
	printf("*pfloat的值为:%f\n", *pfloat);   ——>9.0 真实值  
注意这里的(-1)^0*1.001*2^3只是接近于9.0,浮点数在内存中的存储不是一定精确
	return 0;
}

posted @ 2023-03-27 12:21  Fan_558  阅读(5)  评论(0编辑  收藏  举报  来源