大小端字节序知识详解


 计算机硬件有两种储存数据的方式: 大端字节序( big endian 小端字节序( little endian

举例:

    数值0x2211使用两个字节储存:高位字节是0x22,低位字节是0x11。

    大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法

    小端字节序:低位字节在前,高位字节在后,即以0x1122形式储存。
    怎么去记才不会出错呢?
    其实只需要记住小端是低位字节存低位数据,高位字节存高位数据。(称为:低低高高)

同理:0x1234567的大端字节序和小端字节序的写法如下图:
    

    由图中可以看出:大端小端字节序最小单位为1字节,即8bit;大端字节序就是和我们平时写法的顺序一样,从低地址—>高地址写入0x01234567;而小端字节序就是和我们平时的写法反过来,因为字节序最小单位为1字节,所以从低地址—>高地址写入0x67452301。

      我一直不理解为什么要有字节序,每次读写都要区分,很麻烦!觉得统一使用大端字节序,就很方便。

读了一篇文章,解答了所有的疑问,首先,为什么要有小端字节序?
    
原因是:计算机电路优先处理低位字节,效率比较高,因为计算机都是从低位开始的。所以计算机内部处理都是小端字节序。

    但是人类习惯读写大端字节序,所以除了计算机的内部处,其他的场理合都是大端字节序,比如网络传输和文件储存。

    计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读取字节,先读入第一个字节,再读第二个字节。如果是大端字节序,先读到的是就是高位字节,后读到的就是低位字节。小端字节序正好相反。

    字节序的处理:只有读取的时候,才必须区分字节序,其他情况都不用考虑。
    
    字节序大小端的问题是各公司笔试题的热门,基本上每家公司都会考这样的题目,下面举几个例子,大家一起看一下:
1.如何用程序测试一个平台是大端模式,还是小端模式?
    这题目答案不唯一,有好多种方法都可以实现,我在这里就举两种方法吧,因为其实用那种方法,实现的思想都是一样的。
    ①利用union类型--可以利用union类型数据的特点:所有成员的起始地址一致,1存放在变量i的低位,当变量ch等于1时,就相当于将数据的低位存放到了内存的低地址处,即就是小端模式,反之就是大端模式,代码如下:

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. union check
  3. {
  4.   int i;
  5.   char ch;
  6. }c;
  7. int main()
  8. {
  9.   c.= 1;
  10.   c.ch == 1 ? printf("Little-endian/n") : printf("Big-endian/n");
  11.   return 0;
  12. }
    ②对int强制类型转换,首先取出变量i的地址,强制转换为char *类型,再用*访问,代表取地址长度为1的内容,当取出内容等于1时,就相当于将数据的低位存放到了内存的低地址处,即就是小端模式,反之就是大端模式,

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5.   int i = 1;
  6.   *(char *)&== 1 ? printf("Little-endian/n") : printf("Big-endian/n");
  7.   return 0;
  8. }
   
下面再看一道比较难的题,因为不止涉及到大小端的问题,还涉及到强制类型转换的相关问题:

2.在X86系统下,分别在大端模式和小端模式下,下面函数的值是多少,为什么,请画图说明?
    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;

     }
    我们知道a表示数组首元素的首地址,(int *)(&a+1)就是把&a加1,再转化为int *,因为&a+1就指向a[5]了,ptr1[-1]又相当于ptr1指向了a[4];

    还有(int)a+1就是把地址a转换int型加1,因为int类型是4个字节存储,(int)a+1就指向a[0]的第二个字节的指针了,如下图所示:


    所以小端模式时:ptr1[-1] = 0x04
                             *ptr2 = 0x2000000


    所以大端模式时:ptr1[-1] = 0x04
                             *ptr2 = 0x100

写的很棒!

转载自这里:

大小端字节序知识详解-帝国时代211-ChinaUnix博客

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值