当前位置: 首页 > ds >正文

【c语言】数据在内存中的存储

一、 大小端字节序

大端字节序:数据的低字节内容存放在内存的高地址处,数据的高字节内容存放在内存的低地址处,对于0x11223344
在这里插入图片描述

小端字节序:数据的低字节内容存放在内存的低地址处,数据的高字节内容存放在内存的高地址处,对于0x11223344
在这里插入图片描述

  1. 什么是高字节和低字节
    对于十进制数字:1234,4是低位,1是最高位
    同理,对于十六进制:0x11223344,44是地址字节位,11是高字节位
  2. 为什么会有大小端?
    数据在内存中的存储是以字节为单位的,char类型的变量占8个bit位,1个字节,但除了char类型之外有很多类型的变量大于1个字节,对于位数⼤于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度⼤于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。因此就导致了⼤端存储模式和⼩端存储模式。

二、练习

char默认是有符号的,usigned char 为无符号字符类型,char类型变量大小为1个字节,8个bit位
对于无符号类型,其范围为:0-255,是一个周期性的循环
在这里插入图片描述

对于有符号类型,其范围为:-128~127,也是一个周期性的循环
在这里插入图片描述

2.1. 练习一

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

-1的补码为
11111111 11111111 11111111 11111111
char只能存储8个比特位,为11111111是补码,为-1;
b的值与a一样;
c是无符号,11111111作为补码,对应值为255

2.2. 练习二

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

-128
源码为:10000000 00000000 00000000 10000000
反码为:111111111 111111111 111111111 011111111
补码为:111111111 111111111 111111111 10000000
a中存储的为10000000
打印的是无符号整型,前面要补齐0
则补齐后补码为:00000000 00000000 00000000 10000000
反码为补码取反:11111111 11111111 11111111 01111111
源码为反码+1:11111111 11111111 11111111 10000000
结果为一个很大的值:4294967168

2.3. 练习三

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

由于a是char类型,只能存储-128~127的范围,因此,循环开始后:
-1,-2,…-127,-128,127,126,125…,2,1,0 由于strlen到\0的位置停止计算,因此a的长度为128+127=255

2.4. 练习四

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

对于ptr2,数组a在内存中存储的形式为小端存储: 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00
00 a为首元素地址,强转成int后,+1就是+1
假如首元素地址为0x12ff40,强制转换成整型后+1后为0x12ff41,再将其转换成int*后,为地址,那么地址0x12ff40与0x12ff41相差一个字节,因此ptr2向后走了一个字节,其类型为int*,解引用后拿出的是4个字节,因此ptr2指向的内存空间数据为:
00 00 00 02,由于是小端存储,拿出后排列方式为02 00 00 00 按16进制打印出为0x02000000

三、浮点数在内存中的存储方式

任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:
在这里插入图片描述
例如:
9.5表示成二进制为:1001.1,写成V的形式为:(-1)^0*1.0011*2^3
所以S=0,M=1.0011,E=3
IEEE 754规定:
对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M;
对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M;
以32位为例:
在这里插入图片描述
在存储的过程中,1<M<2,因此默认M的第一位总是1,可以被舍去,只保存小数点后的部分,等到读取的时候再把前面的1加上,这样做的目的是可以节省1个有效数字;对于指数E来说,在存入时候必须加上一个中间值,对于8位的E来说,中间值是127,对于11位的E来说,中间值为1023

以9.5为例:S=0,M=1.0011,E=3,E+127为130,二进制为:10000010
在存入时候,M为00110 00000 00000 00000 000,所以,在存储在内存中的形式为:
0 10000010 00110000000000000000000

浮点数读取的过程:
E不全为0或不全为1:指数E的计算值减去127(或1023),得到真实值,再将有效
数字M前加上第⼀位的1;
E全为0这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字;
E全为1这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s)

练习:

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);return 0;
}

9在内存中的补码为00000000 00000000 00000000 00001001
上面两个printf函数内:站在pFloat的角度来看,补码中的数据是以浮点数的形式存储的,即S、E、M的方式存储,读出的值为0.00000000,这时候E全为0,表示很小的接近于0的数字
下面两个printf函数内:9是以浮点数的形式存储的,二进制位1001.0,(-1)^0*1.001*2^3
S=0,E=3,M=001
0 10000010 0010000000000000000000
以整数形式拿出时候,是一个很大的数字,以浮点出取出时候,就是9.0

在这里插入图片描述

http://www.xdnf.cn/news/3761.html

相关文章:

  • Servlet(二)
  • 怎样提升社交机器人闲聊能力
  • 【Linux】进程优先级与进程切换理解
  • 第38课 常用快捷操作——双击“鼠标左键”进入Properties Panel
  • Linux运维——Vim技巧一
  • LeetCode —— 102. 二叉树的层序遍历
  • 设计模式简述(十七)备忘录模式
  • yolov5 train笔记4 roboflow
  • Android Compose 中 Side Effects 和 State 相关的 API 使用
  • 数据仓库方法论书籍及其阅读建议
  • Linux 库文件详解
  • 自动化测试项目1 --- 唠嗑星球 [软件测试实战 Java 篇]
  • 旧版本NotionNext图片失效最小改动解决思路
  • 解决跨域问题
  • 【质量管理】现代TRIZ问题识别中的功能分析——相互接触分析
  • HarmonyOS NEXT第一课——HarmonyOS介绍
  • FastAPI中的复杂查询与原子更新指南
  • 柔性超声耦合剂的选择与设计-可穿戴式柔性超声耦合剂面临的难题
  • C# 多态性详解:从静态到动态的编程艺术
  • PMP-第七章 项目成本管理(一)
  • 2.1 行列式
  • 【C++】平衡二叉树(AVL树)迭代版
  • 高中数学联赛模拟试题精选学数学系列第7套几何题
  • 【单片机数码管实现第一位开始走0~9,1s后第二位再开始亮】2022-5-2
  • K8S - StatefulSet 与 DaemonSet - 有状态应用部署与节点管理策略
  • QGraphicsView QGraphicsScene QGraphicsItem 的关系
  • 计算几何(简单旋转卡壳)2024昆明邀请赛
  • [FPGA Video IP] Multi-Scaler
  • [Control-Chaos] Heart Broken(心臟破裂)
  • 完整的 VS Code + CMake + Qt + GCC 项目构建方案:EXE 程序与多个 DLL 库