你真的知道数据在内存的存储顺序吗?

一:背景

      话说昨天我居然奇迹般的去上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方式进行数据存储的话,其在内存中的排列方式与其二进制格式表示是一致的。估计大部分比较容易接受这种方式。



 

以上仅为个人感想,如有谬误之处,还望指正。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值