【C语言】整型和浮点型在内存中的存储方式

欢迎━(*`∀´*)ノ亻!,这里是王_哈_哈 Jw~!!!笑一笑呐!!!


目录

内容提要 :

一.关于数据类型

1.数据类型的基本归类

2.通过sizeof查看各种类型的所占的空间(单位为字节)

二.整型在内存中的存储

1.原码反码补码

2.大小端字节序存储

什么是大小端字节序存储?

 如何判断当前机器的字节序?

方法一(用强制类型转化取出一个字节判断)

方法二(使用联合体):

三.浮点型在内存中的存储

1.一个存储差异的栗子

2.浮点数的存储规则

存储模型

存储细节

S

E

M

例子

从内存中拿出

E不全为0或不全为1

E全为0

E全为1

3.解释前面存储差异的栗子


下面是关于这篇博客分享的内容提要 :

【C语言】整型和浮点型在内存中的存储方式_第1张图片


一.关于数据类型

1.数据类型的基本归类

【C语言】整型和浮点型在内存中的存储方式_第2张图片

(char类型本质上是以它的Ascall码值存储的,所以归类到整型。)

2.通过sizeof查看各种类型的所占的空间(单位为字节)

C语言中没有明确规定long的大小,但sizeof(long)一定大于等于sizeof(int)

char占1Byte,8bit!int占4Byte,32bit!float占4Byte,32bit!

【C语言】整型和浮点型在内存中的存储方式_第3张图片


二.整型在内存中的存储

整数在内存中存的是它的补码

1.原码反码补码

原码反码补码是整数的三种表示方法,它们的第一位为符号位(0表示正,1表示负),其余为数值位。原码就是将该整数按正负数的形式直接翻译成二进制。

正数的原反补码相同。

负数的反码:符号位不变,其余位按位取反;补码:反码+1;

例如:

10 

原码:0000 0000 0000 0000 0000 0000 0000 1010

反码:0000 0000 0000 0000 0000 0000 0000 1010

补码:0000 0000 0000 0000 0000 0000 0000 1010

-10

原码:1000 0000 0000 0000 0000 0000 0000 1010

反码:1111 1111 1111 1111 1111 1111 1111 1111 0101(符号位不变,其余位按位取反)

补码:1111 1111 1111 1111 1111 1111 1111 1111 0110(反码+1)

所以当我们在运行

int main()
{
    int a = 10;
    int b = -10;
    return 0;
}

这样一段代码时,计算机在内存中就开辟了两个4字节的空间分别存放a和b的补码。

【C语言】整型和浮点型在内存中的存储方式_第4张图片

(实际上当我们在编译器上进行调试查看内存时为了方便展示,显示的是十六进制的数值)所以理论上当我们查看内存时应该是这样的:

【C语言】整型和浮点型在内存中的存储方式_第5张图片

 但实际上当我们打开vs,输入这段代码,在进入F10调试后,点击调试-->窗口-->内存 分别输入了&a,&b,并将列数改为4看到的结果是:

【C语言】整型和浮点型在内存中的存储方式_第6张图片

 发现每个字节的顺序与我的理论正好颠倒,这是由于计算机的大小端字节序存储的原理。

2.大小端字节序存储

什么是大小端字节序存储?

字节序:以字节为单位的存储顺序。(C语言的数据存储是以字节为单位的,每个地址单元对应一个字节即8bit)。

大端存储模式:数据的低位保存在内存的高地址;

小端存储模式:数据的高位保存的内存的低地址。

【C语言】整型和浮点型在内存中的存储方式_第7张图片

 (对于一个32bit的十六进制数0x11223344来说,11是高位,44是低位)

 如何判断当前机器的字节序?

(我们常用的x86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式,有些ARM处理器还可以用硬件来选择是小端还是大端)

方法一(用强制类型转化取出一个字节判断)

(我们可以用一个程序实现判断:我们创建一个int类型的i,放入一个1,把他转化为正常的十六进制就是0x 00 00 00 01,内存中一个字节一个字节地存储,如果是大端:0x 00 00 00 01,小端:0x 01 00 00 00. 接着我们把本来为int*类型的&i强制类型转化为char*并解引用的值返回,如果是大端就是ox00=0,小端即为0x01=1)

int check_sys()
{
	int i = 1;
	return(*(char*) & i);    //将&i强制类型转化为char*
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

【C语言】整型和浮点型在内存中的存储方式_第8张图片

方法二(使用联合体):

(因为联合体内的数据占的是一块内存,下面这个联合体的内存大小为4个字节,c正好在低字节处,如果是小端存储01和char占同一块内存就会返回1,反之和上面原理一样。)

int check_sys()
{
	union
	{
		int i;
		char c;
	}un;
	un.i = 1;
	return un.c;
}

int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

【C语言】整型和浮点型在内存中的存储方式_第9张图片


三.浮点型在内存中的存储

我们常见的浮点数有3.14,1E10(1.0*10^10)等,常见类型有float,double,long double。它们的表示范围在float.h中定义。浮点数在计算机中也用二进制形式存储,但和整型大相径庭。

1.一个存储差异的栗子

(这里不是把浮点数和整数相互强制转换,而是将他们分别用对方的存储方式解释并打印)

【C语言】整型和浮点型在内存中的存储方式_第10张图片

 当我们把整型9用浮点数存储方式解释之后变成了0.000000,而9.0用整型存储方式(补码)解释之后变成了一个很大的数字,就很六。那么浮点数到底是咋子存储的嘞(色.jpg)

2.浮点数的存储规则

存储模型

根据国际标准IEEE(电器和电子工程协会)754,任意一个二进制浮点数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)^0*1.011*2^2 。此时S=0,M=1.011,E=2
  • 十进制的0.5写成二进制为0.1   →  (-1)^0*1*2^(-1).此时S=0,M=1,E=-1

对于一个32位的浮点数,它的存储模式如下图(对于一个64位的浮点数E占11bit,M占52bit):

【C语言】整型和浮点型在内存中的存储方式_第11张图片

存储细节

S

S存储比较简单,在第一位,正数为0,负数为1.

E

E代表的是指数(二进制的科学计数法,咱可以理解为小数点向哪边移动了多少位,向左移动两位是2,向右移动两位就是-2),实际上是有正有负的,但是E是一个无符号整数(unsigned int)。如果是8位的E,取值范围就是0~255;如果是11位,取值范围0~2047.

为了能够表示正负,IEEE754规定,存入E的真实值必须再加上一个中间数,对于8位的E,这个中间数为127,对于11位的E中间数为1023。比如

5.5的表面E值为2,实际E=2+127=129,即10000001.   

0.5的表面E值为-1,实际E=(-1)+127=126,即01111110.

M

因为M大于等于1小于2,就是1.xxxxxxx,。IEEE754规定反正这个个数一直为1,就不保存,只保存xxxxxxx,所以保存5.5(101.1)时,M=1.011,实际上保存的是011(前面20位补0)

例子

【C语言】整型和浮点型在内存中的存储方式_第12张图片

从内存中拿出

分三种情况,S表示正负

E不全为0或不全为1

将指数E减去127(或1023),得到真实值,再将有效数字M前加上第一位的1

E全为0

指数E=1-127(或1-1023),得到真实值,有效数字M不再加上第一位的1

(如果E全为0的话,说明原来的指数为-127,说明0.00000(126个0)1,就是一个趋于零的数字,正负取决于S)

E全为1

这时,如果有效数字M全为0,表示正负无穷大

3.解释前面存储差异的栗子

1.用浮点数的存储方式解释整数9

int n = 9;内存中是这样的(以9的补码存储):

00000000000000000000000000001001

float* pf = (float*)&n;(我们给计算机洗脑,说这块内存是以浮点数形式存的,所以)

计算机把它分成SEM三部分,第一个0代表正数,后八个为E都是全为0,直接得出0.000000(%f默认六位小数)

2.用整数的存储方式解读浮点数9.0

float i = 9.0;(根据浮点数的存储规则,内存上是这样的:)

0 10000010 00000000000000000000001

int* pi = (int*)&i;(我们给计算机洗脑这不是以浮点数存储方式存储的,是一个补码,所以)

它是一个正数直接转化为十进制,就是刚刚运行出来的结果

【C语言】整型和浮点型在内存中的存储方式_第13张图片


好啦~以上就是这次分享记录的全部内容,真切体验到创作不易了,呜呜呜~我还要还得再改进改进。谢谢支持,谢谢自己~

点个赞赞叭~~

【C语言】整型和浮点型在内存中的存储方式_第14张图片【C语言】整型和浮点型在内存中的存储方式_第15张图片【C语言】整型和浮点型在内存中的存储方式_第16张图片

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