你真的知道数据在内存的存储顺序吗?
2012-11-02 11:08
309 查看
一:背景
话说昨天我居然奇迹般的去上C#课(老师是个美女,大家懂得....),感觉好久没去上她的课了,搞得自己都不好意思了,正好趁这个机会去看看她(不要多想哦,亲)。在课上,老师讲到个文件流的读写的例子,有一段代码引起了我的兴趣,以为是一个很简单的问题,但是运行的结果去让我很吃惊,我顿时有种冲动,想说一句:我靠,这啥玩意!哈哈 ,扯淡了,不多说了,下面我来还原下现场的情形:
首先是把 0 ~19 20个(Int32类型,4个字节)的数字以二进制的形式写到一个文本文件中,我这测试用例为 F: test.txt ;
demo:
接着以每2个字节(即Int16类型)来读取刚刚写入到 F:test.txt 的二进制文本文件。
Demo:
二:问题
上面的二段代码理解起来基本没有什么问题,按照我的常理:因为开始的时候是按每4个字节进行存储的,那么数据的存储顺序应该如下所示:
如果按照每2个字节进行读取的话,那么结果应该是:
但是结果呢?
是不是很吃惊呢?为啥会出现这种情况?这货是啥玩意?
三:解析
于是,我很困惑,非常的困惑,碰到问题,就要解决问题,这是作为软件工程师最基本的要求,在网上找了很久,看的眼睛都花了,最后去CSDN论坛里问了下,坛子了说这与字节序有关,具体什么没有详说,于是拿出我的秘密武器:google. 当看到了字节序的有关概念,了解到数据在内存的排列方式后,这个问题就有解了。于是乎就有了这篇博文,下面我来解解这个问题。
解:(先写个大的解字,哈哈)
在设计计算机系统的时候,有两种处理内存中数据的方法。一种叫为Little-Endian(小端),存放在内存中最低位的数值是来自数据的最右边部分(也就是数据的最低位部分)。与之相对于的是Big-Endian(大端),正好相反,存放在内存中最低位的数值是来自数据的最左边边部分(也就是数据的最高为部分),BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有关的,每一种CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架构(Intel、AMD)的CPU中是Little-Endian,而PowerPC
、SPARC和Motorola处理器是Big-Endian。这其实就是所谓的主机字节序。大部分的人使用的是IA架构的计算机,包括笔者我的本本。可能对于这样的解释有些人还是有些迷惑,下面就以Int32类型的 数字1 为列,分别以Little-Endian 和Big-Endian 来介绍其在内存中的存储顺序。
Little-Endian:将低序字节存储在起始地址
int32类型的数字1其二进制表示为:
则其按照Little-Endian 方式进行数据存储的话,则其在内存中的排列方式为:
即数值在内存中的存储顺序与其二进制表示有点不同,所有如果我按照每2个字节(即int16类型)进行读取的话,取到的数据应该是 1 0 ,正好与结果相吻合。至于之所以这样设计是为了方便计算机处理数据,提供效率。我的机器就是以Little-Endian方式对数据进行存储的。
Big-Endian: 将高序字节存储在起始地址
理解了Little-Endian 的排列方式,那么Big-Endian就不难理解了。下为int32类型的数字1在内存中以Big-Endian方式进行排列图:
从中可以看出,按照Big-Endian方式进行数据存储的话,其在内存中的排列方式与其二进制格式表示是一致的。估计大部分比较容易接受这种方式。
以上仅为个人感想,如有谬误之处,还望指正。
话说昨天我居然奇迹般的去上C#课(老师是个美女,大家懂得....),感觉好久没去上她的课了,搞得自己都不好意思了,正好趁这个机会去看看她(不要多想哦,亲)。在课上,老师讲到个文件流的读写的例子,有一段代码引起了我的兴趣,以为是一个很简单的问题,但是运行的结果去让我很吃惊,我顿时有种冲动,想说一句:我靠,这啥玩意!哈哈 ,扯淡了,不多说了,下面我来还原下现场的情形:
首先是把 0 ~19 20个(Int32类型,4个字节)的数字以二进制的形式写到一个文本文件中,我这测试用例为 F: test.txt ;
demo:
static void Main(string[] args) { //写入数据 string filePath; Console.WriteLine("请输入需要创建的二进制文件路径(包括文件名)"); filePath = Console.ReadLine(); FileStream fileStream = new FileStream(filePath, FileMode.Create); BinaryWriter writer = new BinaryWriter(fileStream); for (int index = 0; index < 20; index++) { writer.Write(index); } Console.WriteLine("写入完毕"); writer.Close(); fileStream.Close(); }
接着以每2个字节(即Int16类型)来读取刚刚写入到 F:test.txt 的二进制文本文件。
Demo:
//读入数据 Console.WriteLine("请输入文件名:"); string filePath = Console.ReadLine(); if (!File.Exists(filePath)) { Console.WriteLine("文件不存在。"); } else { FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(fileStream); try { while (true) { Console.WriteLine(reader.ReadInt16()); } } catch (EndOfStreamException) { Console.WriteLine("已经到文件尾部了"); } finally { reader.Close(); fileStream.Close(); Console.ReadKey(); } }
二:问题
上面的二段代码理解起来基本没有什么问题,按照我的常理:因为开始的时候是按每4个字节进行存储的,那么数据的存储顺序应该如下所示:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000010 ......
如果按照每2个字节进行读取的话,那么结果应该是:
0 0 0 1 0 2 ......
但是结果呢?
是不是很吃惊呢?为啥会出现这种情况?这货是啥玩意?
三:解析
于是,我很困惑,非常的困惑,碰到问题,就要解决问题,这是作为软件工程师最基本的要求,在网上找了很久,看的眼睛都花了,最后去CSDN论坛里问了下,坛子了说这与字节序有关,具体什么没有详说,于是拿出我的秘密武器:google. 当看到了字节序的有关概念,了解到数据在内存的排列方式后,这个问题就有解了。于是乎就有了这篇博文,下面我来解解这个问题。
解:(先写个大的解字,哈哈)
在设计计算机系统的时候,有两种处理内存中数据的方法。一种叫为Little-Endian(小端),存放在内存中最低位的数值是来自数据的最右边部分(也就是数据的最低位部分)。与之相对于的是Big-Endian(大端),正好相反,存放在内存中最低位的数值是来自数据的最左边边部分(也就是数据的最高为部分),BIG-ENDIAN、LITTLE-ENDIAN、跟CPU有关的,每一种CPU不是BIG-ENDIAN就是LITTLE-ENDIAN、。IA架构(Intel、AMD)的CPU中是Little-Endian,而PowerPC
、SPARC和Motorola处理器是Big-Endian。这其实就是所谓的主机字节序。大部分的人使用的是IA架构的计算机,包括笔者我的本本。可能对于这样的解释有些人还是有些迷惑,下面就以Int32类型的 数字1 为列,分别以Little-Endian 和Big-Endian 来介绍其在内存中的存储顺序。
Little-Endian:将低序字节存储在起始地址
int32类型的数字1其二进制表示为:
-----数值高位----- -----数值低位----- 00000000 00000000 00000000 00000001
则其按照Little-Endian 方式进行数据存储的话,则其在内存中的排列方式为:
地址低位 地址高位 --------------------------------------->地址逐渐增大 00000000 000000001 00000000 00000000 -----数值低位------ ------数值高位----
即数值在内存中的存储顺序与其二进制表示有点不同,所有如果我按照每2个字节(即int16类型)进行读取的话,取到的数据应该是 1 0 ,正好与结果相吻合。至于之所以这样设计是为了方便计算机处理数据,提供效率。我的机器就是以Little-Endian方式对数据进行存储的。
Big-Endian: 将高序字节存储在起始地址
理解了Little-Endian 的排列方式,那么Big-Endian就不难理解了。下为int32类型的数字1在内存中以Big-Endian方式进行排列图:
地址低位 地址高位 ---------------------------------------->地址逐渐增大 00000000 00000000 00000000 00000001 ----数值高位------ ------数值低位------
从中可以看出,按照Big-Endian方式进行数据存储的话,其在内存中的排列方式与其二进制格式表示是一致的。估计大部分比较容易接受这种方式。
以上仅为个人感想,如有谬误之处,还望指正。
相关文章推荐
- 四种数据存储结构---顺序存储 链接存储 索引存储 散列存储
- 在C语言中,基本类型数据在内存中的存储形式
- Android三级存储——将网络数据存储到内存和缓存
- javascript ArrayBuffer类型化数组和视图的操作 个人理解类型化数据就是内存分配区域,不同数据的存储就是视图DataView咯 var buffers = []; var jso
- JAVA 内存管理总结:内存泄露、数据存储、垃圾回收机制一网打尽!
- 看数据结构写代码(22) 二叉树的顺序存储方式
- [数据结构]四种数据存储结构---顺序存储 链接存储 索引存储 散列存储
- 如何在数据库中存储有顺序的数据
- 华为OJ 初级:求int型数据在内存中存储时1的个数
- 第一部分 数据内存存储、常预定义值类型、用户自定义值类型、预定义引用类型
- float数据在内存中是怎么存储的
- C++ 内存分配 数据存储
- java中数据类型在内存中存储的方式
- JAVA数据结构之线性表的顺序存储
- 【华为OJ】【041-求int型数据在内存中存储时1的个数】
- 一个小菜鸟对数据在内存中的二进制存储的理解
- 数据结构之线性表-顺序存储
- 数据结构-顺序存储-线性表-基本运算
- C学习笔记2-int类型数据在内存中的存储形式
- 浮点型数据在内存中存储的表示[转载]