数据在内存中的存储

文章详细介绍了大小端字节序的概念及其原因,以及整数和浮点数在内存中的存储方式,包括补码表示、IEEE754标准下的32/64位浮点数表示。通过示例和练习题展示了如何判断机器字节序和处理整数/浮点数的内存操作。
摘要由CSDN通过智能技术生成

1.大小端字节序

1.1 大小端字节序的概念

    大端模式:将数据的低位字节内容保存到内存的高地址处,数据的高位字节内容保存到内存的低地址处;

    小端模式:将数据的低位字节内容保存到内存的低地址处,数据的高位字节内容保存到内存的高地址处;

例: 一个16bit的short型x,在内存中的地址是0x0010,x的值是0x1122。那么 ,0x11是高字节,0x22是低字节。如果是大端模式,那么 0x11在低地址处,即0x0010中,0x22放在高地址处,即0x0011中。

1.2 为什么会有大小端字节序

(1)方便处理多字节的数据类型;

(2)  对于位数大于8bit的处理器(如 16位处理器 或者 32位处理器)由于寄存器的宽度大于1个字节,那么大小端字节序被用来处理存放占有多个字节的数据的问题。

>> 判断当前机器的大小端字节序

#include <stdio.h>

int main()
{
	int i = 0;
	int p = *(char*)&i;

	if (p)
		printf("大端\n");
	else
		printf("小端\n");

	return 0;
}

2. 整数在内存中的存储

2.1 理论简述

对于整形数据,数据存放在内存中的其实是补码

为什么 ?

(1)在计算机系统中,数值一律使用补码表示和存储。因为,使用补码可以将符号位和数值域统一处理;

(2) 加法减法也可以统一处理(CPU只有加法器);

(3)补码和原码相互转换,运算过程相同,不需要额外的硬件电路;

【知识回顾 : 原码,反码,补码】

整数有三种二进制表示方式:原码,反码,补码

这三种表示方式均有符号位和数值位,符号位都是用 0 表示 “正”,用 1 表示 “负”;

                                                             数值位最高位的一位被当成符号位,其余都是数值位;

正整数的原码、反码 、补码都相同。

负整数的原码、反码、补码各不相同:

原码:直接将数值按照正负数形式翻译成二进制得到;

反码:原码符号位不变,其他位按位取反;

补码:反码 + 1;

原码 ——> 补码  : 取反 ,+ 1;     补码 —— > 原码 : 取反 ,+ 1

>> 2.2 经典题目 

  题目1

#include <stdio.h>
int main()
{
	char a = -1;
	signed char b = -1; //char 是 signed char 还是 unsigned char 并不确定,这取决于编译器;
	                    // 在VS编译器里,char 等同于 signed char
	unsigned char c = 1;
	printf("a = %d ,b = %d ,c = %d",a, b, c);  // %d 十进制打印有符号整型
	return 0;
}

运行结果 : 

为什么是这个结果呢? 

在内存中,-1是按照补码存储的;由于char只占1个字节,所以只会留下最后8个bit的数字;a 截断之后,进行整型提升(由于最高位是1,所以之前的位全部补1,直至填满32位),此时的结果仍然是补码,再转换成原码; c 同理,只是进行整型提升的时候最高位是 0,所以全部补0;

  >> 题目2   

        比较两个代码  两者的结果是否不同?

#include <stdio.h>

int main()
{
	char a = -128; // 有符号char 取值范围   -128~127
	printf("%u\n", a); // %u 打印无符号整型
	return 0;
}

#include <stdio.h>

int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}

 两者结果均为 :    (本题原理类似题目1 )

 

 >> 题目3

#include <stdio.h>

int main()
{
	char arr[1000];
	for (int i = 0; i < 1000; i++)
	{
		arr[i] = -1 - i;
	}
	printf("%d", strlen(arr));
	return 0;
}

      猜猜运行结果是多少 ?😛 😝

   当当!!    

   char 的取值范围是 -128 ~ 127       

   可以用下面这张图来解释结果

 数据在内存中都是以补码形式存放,由于char只占8个bit位,所以只有最后8 bit位的数据保留。只有最后8bit位的数据进行加减,-128 - 1的结果变成127。如此循环往复,周而复始。128 + 127 = 255

>> 题目4

      比较两个代码 它们的结果分别是什么呢?

// 1
#include <stdio.h>

unsigned int i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello c\n");
	}
	return 0;
}


// 2
#include <stdio.h>

int main()
{
	unsigned int i = 0;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}

     两个代码都会陷入死循环 

对于代码1 ,unsigned int 的取值范围是 0~ 255, 所以for 循环里面的限制条件 i <= 255  对于任意一个 i 都是恒成立 ,所以循环永远不会停止;   对于代码2,同理,i >= 0 恒成立 ,所以程序也会无限循环下去;     

>>>>  那么浮点数和整数在内存中的存储方式一样吗? <<<<

#include <stdio.h>

int main()
{
	int n = 9;
	float* p = (float*)&n;
	printf("n = %d\n", n);
	printf("*p = %f\n", *p);

	*p = 9.0;
	printf("n = %d\n", n);
	printf("*p = %f\n", *p);

	return 0;
}

运行结果 :  

由此看出 浮点数和整数在内存中的储存方式不同

3. 浮点数在内存中的存储

3.1 简述

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

V = ( -1 )^S * M * 2^E;

其中,(-1)^S 表示符号位,当 S = 0, V 为正数;当 S =1 时,V 为负数;

               M  表示有效数字,1 <= M  < 2;

               2 ^E 表示指数位;

例: 十进制的5.0 ,写成二进制是101.0 ,相当于 1.01 * 2^2 

         此时,S = 0; M  = 1.01; E = 2;

IEEE 754规定:

对于32位浮点数,最高一位存储符号位S,接着的8位存储指数E,剩余的23位存储有效数字M;

对于64位浮点数,最高的一位存储符号位S,接着的11位存储指数E,剩余的52位存储有效数字M

 

 3.2 浮点数存的过程

M :

由于 1 <= M < 2, 所以M可以写成  1.xxxxxxx 的形式 (其中,xxxxxx表示小数部分)

IEEE 754 规定,计算机内部保存M 时,默认这个数字的第一位总是1,因此1可以被舍弃,只保存后面的小数部分;

E :

E  是无符号整数 ,然而在科学计数法里面,E可以是负数。所以IEE 754 规定,存入内存时,E的真实值必须再加上一个中间数。如果 E 是8位,中间数是127;如果 E 是11 位,中间数是1023。

3.3 浮点数取的过程

(1) E 不全为0或1(有1有0)

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

(2)  E全为0

此时E = 1-127 (或 1-1023),有效数字不再加上第一位的1,而是还原成 0.xxxxxx的小数。这是表示 +0 或 -0 或接近0的很小的数字。 (打印结果一般为0.000000,因为2^127非常大)

(3)E全为1

此时若有效数字M全为0,表示无穷大(或 负无穷大)

                                         

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值