首页 > 系统相关 >C语言:数据在内存中的存储

C语言:数据在内存中的存储

时间:2024-09-11 13:52:16浏览次数:13  
标签:存储 字节 二进制 浮点数 补码 C语言 内存

一.整数在内存中的存储

首先,在讲解操作符的时候,我们就已经知道了,对于整形来说:数据存放内存中其实存放的是补码。并且我们也知道补码是整数的2进制表示方法之一。

整数的2进制表示方法有三种,即 原码、反码和补码

有符号的整数,三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,最高位的一位是被当做符号位,剩余的都是数值位。

正整数的原、反、补码都相同。 负整数的三种表示方法各不相同。

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

反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。

补码:反码+1就得到补码。

注:补码取反,再+1可得到原码。

但为什么存放的示补码,而不是原码呢 ?

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

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

首先我们先看下,下面的代码,我们发现再vs调试下a的数字是以字节为单位倒着存放的,这是因为字节的数据在内存中存储的时候,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储,而在vs中我们是以小端字节序存储。

1.什么是大小端字节存储?

当然在我们了解之前,我们还要知道什么是高位字节和地位字节。

一般来说字节的高低就是左边的为高字节右边的为低字节

例如 0x11223344 其中 11为高字节,44为低字节。

在二进制中11100010 00000000 11110000 11111000 其中11100010为高字节,11111000为低字节。

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

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

2. 判断为大端还是小端

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

 3.计算a的长度

#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;
}

我们知道字符的大小为一个字节,在二进制中一个字节为8bit所以字节的大小是从00000000到11111111,对于有符号的char来说,他的范围是-128~127,所以我们得出来的结果应为255.

 

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

1.浮点数的存储

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

V   =(−1)^S∗ M ∗ 2^E

S 表示符号位,当S=0,V为正数;当S=1,V为负数

• M 表示有效数字,M是大于等于1,小于2的

• 2 E 表示指数位

⼗进制的5.5 ,写成二进制是101.1

1       0       1      .    1

|         |        |            |

2^2    2^1   2^0        2^-1

相当于1.011*2^2

其中S=0, M=1.011 ,E=2.

IEEE 754规定:

对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M

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

其中M是一个大于1小于2的数 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。

对于指数E,它其实是一个无符号整数,如果E为8位,它的取值范围为0~255,如果E为11位,它的取值范围为0~2047,但是,我们知道,科学计数法中的E是可以出现负数的,所以为了防止这种情况,所以IEEE 754规定,存入内存时E的真实值必须再加上 一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。所以当我们保存浮点数的时候,我们要让E加上127或1023之后再转换成二进制的形式存储。

当然,既然我们存储了浮点数,之后我们肯定需要取出浮点数,进行计算,那么我们该如何取出浮点数呢?

2.浮点数取的过程

既然,我们存储浮点数的时候需要改变E的值,那么我们要取出浮点数的时候,也一定要改变E的值即让E-127或-1023。

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

然而指数E从内存中取出可以分成三种情况:

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

例如5.5的二进制是101.1可以写成1.011*2*2

可以得到S=0,M=1.011,E=2

32位下E=2+127=129

0 10000001 01100000000000000000000

可得到数值为1085276160

(2)E全为0

这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

0 00000000 00100000000000000000000

这是E加完之后的二进制形式,发现E的二进制形式全为0,那么E=1-128(或者1-1023),得到才是原来的E=-127或-1022,然而2的-128次幂是一个分母很大的数,所以我们最后得到的数值就会变得趋于零

所以最后的值是接近于0的很小的数字

(3)E全为1 

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

0 11111111 00010000000000000000000

当然这还是E加完之后的二进制形式,而8位二进制全为1的数值位255,那么255-127=128,而2的128次幂是一个很大的数,所以当E全为1时代表这无穷的数,而符合由S的值来决定。

 好了,今天我们就讲的到这里吧,我们下一篇见!

                        

标签:存储,字节,二进制,浮点数,补码,C语言,内存
From: https://blog.csdn.net/zm3rttqs9f/article/details/142137697

相关文章

  • 如何在 Linux 系统中查看 CPU 核数和内存大小
     在日常运维和开发中,了解服务器或虚拟机的硬件配置是非常重要的一环。无论是进行性能调优,还是资源分配,了解CPU的核数和内存大小可以帮助我们更好地规划应用的运行环境。本篇博客将介绍如何在Linux系统中查看CPU核数和内存大小。一、查看CPU核数在Linux中,查看CPU......
  • uniapp 将数据存储在本地缓存setStorage及从本地缓存中异步获取getStorage
    一、uni.setStorage(OBJECT)将数据存储在本地缓存中指定的key中,会覆盖掉原来该key对应的内容,这是一个异步接口。HarmonyOSNext兼容性HarmonyOSNextHBuilderX4.23OBJECT参数说明参数名类型必填说明keyString是本地缓存中的指定的keydat......
  • C语言中的磁盘映射与共享内存详解
    文章目录C语言中的磁盘映射与共享内存1.磁盘映射(MemoryMapping)1.1磁盘映射的深入概念1.2`mmap`函数的详细参数解析1.3磁盘映射的高级应用场景1.3.1大文件处理1.3.2内存共享1.3.3文件与内存同步1.3.4内存映射数据库1.4完整的磁盘映射代码示例1.5注意事项2.......
  • C语言的正则表达式
    C标准库不支持正则表达式,但大部分Linux发行版本都带有第三方的正则表达式函数库。以常见的<regex.h>为例:/*regcomp将正则表达式编译成适合后续regexec函数搜索的形式preg指向模式缓冲区,传出参数regex字符串,传入参数cflag决定编译类型,可位或:-REG_EXTENDED扩展正则表达式......
  • 数据在内存中的存储
    今天学习数据在内存中的存储目录1.整数在内存中的存储基础概念注意对于整形来说:数据存放内存中其实存放的是补码。2.大小端字节序和字节序判断2.1大小端概念**大端(存储)模式:****小端(存储)模式:**2.2为什么有大小端例3.浮点数在内存中的存储3.1浮点数的存储举例来说:IE......
  • 动态内存管理
    C/C++malloc-free底层原理-动态内存管理关于动态内存管理这块在面试中被考察频率非常高,切入的点也很多,有从操作系统虚拟内存问起的,也有从malloc、new等开始问起的。但是无外乎就是两块内容:虚拟内存机制:物理和虚拟地址空间、TLB页表、内存映射动态内存管理:内存管理、分配......
  • 981. 基于时间的键值存储
    题目链接981.基于时间的键值存储思路哈希+二分题解链接哈希表+二分关键点理解题意时间复杂度\(O(\logn)\)空间复杂度\(O(n)\)代码实现:classTimeMap:def__init__(self):self.dct=defaultdict(list)defset(self,key:s......
  • C语言程序设计(初识C语言后部分)
    晴天也会突然下暴雨,温柔的人也会不开心。二十一,实用调试技巧1.什么是bug?2.调试是什么?有多重要?3.debug和release的介绍4.vs环境调试介绍5.如何写出好(易于调试)的代码6.编程常见的错误1.什么是bug?就是使计算机程序或者计算机硬件出现问题,不能正常运行的地方称为bug(缺陷......
  • 【整理】虚拟地址全解析:操作系统内存管理与进程调度的深度揭秘!
    原创freedom47概述在现代计算机系统中,虚拟地址是内存管理的关键组成部分。虚拟地址不仅帮助操作系统高效地管理物理内存,还在进程的内存分配中发挥重要作用。本文将详细介绍虚拟地址的定义、作用、操作系统的内存管理、进程内存分配、32位与64位架构的内存分配差异,以及物......
  • 什么是内存不安全
    内存不安全:是指计算机程序中存在可能导致程序崩溃,数据泄露或者恶意攻击的漏洞。这种问题通常涉及到对内存的错误操作,可能导致程序访问问未分配的内存、访问已经释放的内存、越界访问数组等情况。​ 从硬件层面来看,内存不安全可能涉及到内存泄漏、缓冲区溢出等问题。比如,当程序......