四联光电智能照明论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2715|回复: 0
打印 上一主题 下一主题

大端模式和小端模式转化

[复制链接]
  • TA的每日心情
    开心
    2018-11-9 08:52
  • 241

    主题

    691

    帖子

    7652

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    7652
    跳转到指定楼层
    楼主
    发表于 2016-11-25 11:48:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

    在工作中遇到一个问题,数据是以大端模式存储的,而机器是小端模式,必须进行转换,否则使用时会出问题。

    一、定义:
    大端模式(Big Endian):数据的高字节,保存在内存的低地址中;数据的低字节,保存在内存的高地址中。
    小端模式(Little Endian):数据的高字节,保存在内存的高地址中;数据的低字节,保存在内存的低地址中。

    例如:
    16位宽的数0x1234,在不同的模式下,存储方式为:
                            0x4000        0x4001
    小端模式        0x34        0x12
    大端模式        0x12        0x34

    32位宽的数0x12345678,在不同的模式下,存储方式为:
                            0x4000        0x4001        0x4002        0x4003
    小端模式        0x78        0x56        0x34        0x12
    大端模式        0x12        0x34        0x56        0x78

    二、判断大端模式和小端模式
    使用联合,通过判断首个成员的值,确定是大端还是小端模式:

    1. bool IsBigEndian(){   
    2.     union NUM{  
    3.         int a;   
    4.         char b;   
    5.     }num;   
    6.     num.a = 0x1234;   
    7.     if( num.b == 0x12 ){   
    8.         return true;   
    9.     }     
    10.     return false;   
    11. }
    复制代码


    三、大端模式和小端模式转换
    对32位的数,即4个字节,大端转换成小端:

    方法1:使用移位运算。

    1. uint32_t reversebytes_uint32t(uint32_t value){  
    2.     return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |   
    3.         (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;   
    4. }
    复制代码

    上述代码中,将低8位(0~8位)左移24位,变成了高8位(24~32位),8~16位左移8位变成了(16~24位)。将原高8位和高16位右移,变成了新的低8位和低16位。
    这种方法效率采用了移位运算,效率很高。而且该方法亦可用于小端模式转成大端模式。

    有了32位的转换方法,对64位,即8个字节的转换同理。不过直接写移位运算未免麻烦,可以直接使用上述函数:

    1. // 先将64位的低32位转成小端模式,再将64位的高32位转成小端模式  
    2. // 在将原来的低32位放置到高32位,原来的高32位放置到低32位  
    3. uint64_t reversebytes_uint64t(uint64_t value){  
    4.     uint32_t high_uint64 = uint64_t(reversebytes_uint32t(uint32_t(value)));         // 低32位转成小端  
    5.     uint64_t low_uint64 = (uint64_t)reversebytes_uint32t(uint32_t(value >> 32));    // 高32位转成小端  
    6.     return (high_uint64 << 32) + low_uint64;  
    7. }
    复制代码

    方法2:对每个字节依次处理。
    比如0x12345678,小端模式下可认为是12*(2^32) + 34*(2^16) + 56*(2^8) + 78*(2^0)。在大端模式下,排列顺序发生了变化。

    1. uint32_t changeEndian_uint32t(uint32_t value){  
    2.     char* ptr = (char*)(&value);  
    3.       
    4.     uint64_t base[4];                   // 设置基  
    5.     base[0] = 1;  
    6.     for(int i = 1; i < 4; ++i){  
    7.         base[i] = base[i-1] * 256;  
    8.     }  
    9.   
    10.     uint32_t res = 0;  
    11.     for(int i = 0; i < sizeof(value); ++ i){  
    12.         res += uint8_t(ptr[i]) * base[4-i-1];  
    13.     }  
    14.   
    15.     return res;  
    16. }  
    复制代码

    上述代码中,第一句将输入的uint32_t的变量强制转换成字符类型数组,以便一个字节一个字节的处理。

    参考:

    http://baike.baidu.com/link?url= ... jOlyve2Ze2HQyJqIvb_
    http://blog.163.com/leng_zzu@126 ... 027201161210511469/
    http://www.360doc.com/content/12/0727/08/10389317_226700605.shtml
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|Silian Lighting+ ( 蜀ICP备14004521号-1 )

    GMT+8, 2024-4-25 12:44 , Processed in 1.062500 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表