数据在内存中的存储

目录

整数在内存中的存储

整数二进制的三种表示

 大小端字节序和字节序判断

整数在内存中存储相关的题目

题目1

题目2

题目3

题目4

题目5

题目6

题目7

浮点数在内存中的存储

浮点数存的过程

浮点数取的过程

1、E不全为0或不全为1

2、E全为0

3、E全为1

浮点数题目


整数在内存中的存储

整数二进制的三种表示

整数的二进制表示方法有三种:原码、反码、补码三种表示方法均有符号位和数值位两部分

其中最高位是符号位,用0表示正,1表示负。

整数在内存中存储的是二进制的补码形式,其中正整数的原码等于反码等于补码,而负整数的三种码各不相同。

二进制的三种表示方法:

原码:将数值按照正负的形式翻译成二进制的形式。

反码:将原码中除了符号位,其它的二进制位取反。

补码:将反码加1。

为什么整数在内存中存放的是其补码形式呢:

原理:  
   在计算机系统中,数值⼀律⽤补码来表⽰和存储。 原因在于,使⽤补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是 相同的,不需要额外的硬件电路


 大小端字节序和字节序判断

超过一个字节的数据在内存中存储时,就有存储顺序的问题,存储顺序分为:大端字节序存储、小端字节序存储。

假设有一块内存如下:
内存中存放了一个整型数据(用16进制形式表示)

大端字节序存储:数据的低位字节内容存储在内存的高地址处,而数据的高位字节内容存储在内存的低地址处。

小端字节序存储:数据的低位字节内容存储在内存的低地址处,而数据的高位字节内容存储在内存的高地址处。

#include <stdio.h>

int main() {
	int a = 0x11223344;
	return 0;
}

在vs2022中运行上述代码,进入调试页面查看0x11223344在内存中的存储

我们可以发现,44是一个低位字节内容,存放在了低地址处,所以是小端存储模式。

那么采用哪种模式与什么有关呢?

采用大端存储(Big Endian)还是小端存储(Little Endian)与处理器架构和硬件设备有关

一些处理器架构如 Motorola 68k、SPARC 等采用大端存储模式,一些处理器架构如 x86(Intel 和 AMD)、ARM 等采用小端存储模式

不同的处理器架构和硬件设备可能采用不同的存储模式,因此在编程时需要考虑处理器的字节序,以确保数据在不同平台上的正确解释和交互。

在实际应用中,字节序问题可能会影响数据的传输和交换。例如,在网络通信中,不同设备之间需要互相传输数据,就需要考虑处理器的字节序,以确保数据的正确传输和解释。


整数在内存中存储相关的题目

题目1

请简述⼤端字节序和⼩端字节序的概念,设计⼀个小程序来判断当前机器的字节序。(10分)-百度笔试题 

#include <stdio.h>
int check_sys()
{
	int i = 1;
	return (*(char*)&i);
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("⼩端\n");
	}
	else
	{
		printf("⼤端\n");
	}
	return 0;
}

将i的地址类型转为char*类型的,解引用后只访问一个字节中的内容,所以拿出的可能是字节 00 或 字节 01,当为字节01时即是小端存储


题目2

#include <stdio.h>
int main()
{
	char a = -1;
	signed char b = -1;
	unsigned char c = -1;
	printf("a=%d,b=%d,c=%d", a, b, c);
	return 0;
}

结果为:a = -1, b = -1, c = 255

char 类型的数据取值范围是:-128 ~ 127  , unsigned char 类型的数据取值范围:0 ~ 255
在这里要先说明一点:在内存中数据的运算通常都是数值的补码形式进行运算的 

char默认是signed char 类型,所以 signed char类型的变量存入 -1 时的变化如下图:

上述过程中整型提升的原因是:%d打印的是整数类型,要将char类型提升为int类型,所以将这个数值的补码形式进行高位的扩充至32位。

 unsigned char 类型的变量存入整型-1在内存中的变化如下:

 题目3

#include <stdio.h>
int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}

 -128存入a时的变化如下:

 题目4

#include <stdio.h>
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}

 解题如下:

 题目5

#include <stdio.h>
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d", strlen(a));
	return 0;
}

                                                           (二进制以补码的形式进行加减1)

strlen统计\0(它的ASCII码值是0)之前的个数,-1到-128 有128个数,127到1有127个数,所以128+127=255,结果为255

题目6

#include <stdio.h>
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

unsigned char 类型的数据范围在 0~255

255再加1就变为了0,造成了死循环

题目7

#include <stdio.h>
int main()
{
 int a[4] = { 1, 2, 3, 4 };
 int *ptr1 = (int *)(&a + 1);
 int *ptr2 = (int *)((int)a + 1);
 printf("%x,%x", ptr1[-1], *ptr2);
 return 0;
}

所以ptr[-1]为4,用%x打印出的结果是0x4

假设a的地址为0x12ff40,(int)a表示将地址转化为了一个整数,加1变为0x12ff41,再强制类型转换为(int*)类型的地址,则地址0x12ff41对于地址0x12ff40是往后位移了一个字节的空间大小


*ptr2访问4个字节,从地址0x12ff41处往后找四个字节(上图中的红框),即00 00 00 02,所以用%x打印出的结果是0x02000000


浮点数在内存中的存储

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

 
例如:

1、十进制浮点数0.5的二进制浮点数是0.1(1的权重是2^-1次方,为0.5),S = 0,M = 1.0,E = -1,用上述的公式表示:(-1)^0 * 1.0 * 2^-1

2、十进制浮点数-5.5的二进制浮点数是-101.1,S = -1,M = 1.011,E = 2,相当于 (-1)^1 * 1.011 * 2^2

IEEE 754规定:

对于32位的浮点数(float),首位存S的值,往后走8位存E的值,剩下的23位存M的值。

 对于64位的浮点数(double),首位存S的值,往后走11位存E的值,剩下的52位存M的值。

浮点数存的过程

E和M在内存中存储时比较特殊。

(以下均已32位的浮点数进行举例)

 在内存中存储M时,小数点前的数默认为1,并且省略,只保存小数点后的数。比如1.01,只保存后面的01,补齐0到23位。

在内存中存储E时,如果E为8位,则它的取值范围是0~255,如果为11位,取值范围是0~2047
但公式中的E(科学计数法)是可以为负数的,所以IEEE 754规定,对于8位的E,它的值必须再加上127;对于11位的E,它的值必须再加上1023。对于32位的浮点数,当E为2时,它存储时为2+127 = 129,转为2进制为 1000 0001。

十进制浮点数5.5在内存中的存储为:  

1、先将5.5转为二进制形式:101.1

2、101.1 = (-1)^0 + 1.011 * 2^2 ,通过公式我们可知S=0,E=2,M=1.011

3、S为0,M去掉小数点前的1,将011后面补0到23位即01100000000000000000000,E的值加127为129转为二进制存储为10000001

最后的结果为:

0 10000001 01100000000000000000000

 浮点数取的过程

在内存中取出浮点数要分为三种情况

1、E不全为0或不全为1

 0 10000001 01100000000000000000000

此浮点数的E不全为0也不全为1,这时,浮点数就采用下面的规则进行表示,首先第一位是S,即S=0。接着8位是指数E,10000001转为十进制减去127得到真实值,即E=2。后面的23位是M,将M的有效值011前面加上1,即M=1.011,因此取出的结果为 (-1)^0 * 1.011 * 2^2 ,运算后转为十进制为 5.5

2、E全为0

 0 00000000 01100000000000000000000 

此时的E全为0,则E等于1-127(1-1023) 即为真实值,即E = -126 ,有效数字M不再加上第一位的1,即M=0.011,取出的结果为:(-1)^0 * 0.011 * 2^(-126)  ,结果是一个接近于0的数,用十进制小数表示就是0.000000

3、E全为1

0 11111111 01100000000000000000000 

 当E在内存中为全1时,11111111转为10进制为255减去127为128,M为1.011

结果为:(-1)^0 * 1.011*2^128 是一个非常大的一个数,它表示一个正无穷大,当S为1时它表示负无穷大。

浮点数题目

#include <stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
}

*pFloat的值:

 num的值:


创作不易,看到这里麻烦请点一个免费的赞哟~~

相关推荐

  1. 数据内存存储

    2024-03-24 15:24:01       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-24 15:24:01       17 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-24 15:24:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-24 15:24:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-24 15:24:01       18 阅读

热门阅读

  1. 小白学习微信小程序开发中的用户登录与授权

    2024-03-24 15:24:01       19 阅读
  2. spaCy NLP库的模型的下载、安装和使用说明书

    2024-03-24 15:24:01       17 阅读
  3. 物联网的介绍

    2024-03-24 15:24:01       19 阅读
  4. 【Ubuntu】远程帮助别人安装软件

    2024-03-24 15:24:01       18 阅读
  5. 279. 完全平方数

    2024-03-24 15:24:01       20 阅读
  6. Android中的前台Service

    2024-03-24 15:24:01       19 阅读
  7. 【CSP试题回顾】202303-2-垦田计划(优化)

    2024-03-24 15:24:01       22 阅读
  8. FFMpeg 获取音频音量、提高音量

    2024-03-24 15:24:01       18 阅读
  9. Spring Boot2

    2024-03-24 15:24:01       14 阅读
  10. FFmpeg滤波器创建

    2024-03-24 15:24:01       16 阅读