zoukankan      html  css  js  c++  java
  • 大小端的区别和判断

    在代码中看到往寄存器写数据的时候,使用到
    *((volatile uint32_t *)(address)) = cpu_to_le32(value),进一步追踪,
    #if __BYTE_ORDER == __LITTLE_ENDIAN
    #define cpu_to_le16(x) (x)
    #define cpu_to_le32(x) (x)
    #define SWAP16(x) do { ; } while(0)
    #define SWAP32(x) do { ; } while(0)
    #else   //大端模式
    #define cpu_to_le16(x) swab16(x)
    #define cpu_to_le32(x) swab32(x)
    #define SWAP16(x) do { x = swab16(x); } while(0)
    #define SWAP32(x) do { x = swab32(x); } while(0)
    #endif

    #define swab32(x)            
            ((unsigned int)(                                //大端模式,将最高有效位移到最低位
                    (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) |
                    (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) |
                    (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) |
                    (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))

    下面这篇文章是从网上看到的,我这里引用一下。
    一、概念及详解
    在各种体系的计算机中通常采用的字节存储机制主要有两种: big-endian和little-endian,即大端模式和小端模式。
    先回顾两个关键词,MSB和LSB:
    MSB:Most Significant Bit ------- 最高有效位
        LSB:Least Significant Bit ------- 最低有效位
    大端模式(big-edian)
    big-endian:MSB存放在最低端的地址上。
    举例,双字节数0x1234以big-endian的方式存在起始地址0x00002000中:
      | data |<-- address
            | 0x12 |<-- 0x00002000
            | 0x34 |<-- 0x00002001
    在Big-Endian中,对于bit序列中的序号编排方式如下(以双字节数0x8B8A为例):
     bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
            ------MSB----------------------------------LSB
            val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
            +--------------------------------------------+
            = 0x8 B 8 A
    小端模式(little-endian)
    little-endian:LSB存放在最低端的地址上。
    举例,双字节数0x1234以little-endian的方式存在起始地址0x00002000中:
     | data |<-- address
            | 0x34 |<-- 0x00002000
            | 0x12 |<-- 0x00002001
    在Little-Endian中,对于bit序列中的序号编排和Big-Endian刚好相反,其方式如下(以双字节数0x8B8A为例):
     bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
            ------MSB-----------------------------------LSB
            val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
            +---------------------------------------------+
            = 0x8 B 8 A
    二、数组在大端小端情况下的存储:
    以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
    Big-Endian: 低地址存放高位,如下:
     高地址
            ---------------
            buf[3] (0x78) -- 低位
            buf[2] (0x56)
            buf[1] (0x34)
            buf[0] (0x12) -- 高位
            ---------------
            低地址
     Little-Endian: 低地址存放低位,如下:
     高地址
            ---------------
            buf[3] (0x12) -- 高位
            buf[2] (0x34)
            buf[1] (0x56)
            buf[0] (0x78) -- 低位
            --------------
            低地址
    三、大端小端转换方法:
    Big-Endian转换成Little-Endian如下:
     #define BigtoLittle16(A)                 ((((uint16)(A) & 0xff00) >> 8) |
                                                 (((uint16)(A) & 0x00ff) << 8))
                                                
        #define BigtoLittle32(A)                 ((((uint32)(A) & 0xff000000) >> 24) |
                                             (((uint32)(A) & 0x00ff0000) >> 8) |
                                             (((uint32)(A) & 0x0000ff00) << 8) |
                                             (((uint32)(A) & 0x000000ff) << 24))
    四、大端小端检测方法:
    如何检查处理器是big-endian还是little-endian?
    联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。
     

     

        /*return 1: little-endian, return 0:big-endian*/
        int checkCPUendian()
        {
            union
            {
                    unsigned int a;
                    unsigned char b;
            }c;
            c.a = 1;
            return (c.b== 1);
        }
        
        //当然,不一定要用联合体的
        int checkCPUendian()
        {
            short data=0x0001;
            char *pCh=NULL;
            
            pCh = (char*)&data; //取地地址字节
            return *pCh;
        }

  • 相关阅读:
    自然语言交流系统 phxnet团队 创新实训 项目博客 (十一)
    install ubuntu on Android mobile phone
    Mac OS, Mac OSX 与Darwin
    About darwin OS
    自然语言交流系统 phxnet团队 创新实训 项目博客 (十)
    Linux下编译安装qemu和libvirt
    libvirt(virsh命令总结)
    深入浅出 kvm qemu libvirt
    自然语言交流系统 phxnet团队 创新实训 项目博客 (九)
    自然语言交流系统 phxnet团队 创新实训 项目博客 (八)
  • 原文地址:https://www.cnblogs.com/riasky/p/3508756.html
Copyright © 2011-2022 走看看