打造自己的字节序转换函数(16位、32位和64位)

http://blog.csdn.net/hongqun/article/details/6092210
在计算机科学领域中,字节序是指存放多字节数据的字节(byte)的顺序,典型的情况是整数在内存中的存放方式和网络传输的传输顺序。不同的处理器所采用的字节序可能是不同的,例如:
 x86,6502Z80VAX,和 PDP-11都是采用小端字节序,而 Motorola 6800 、 68kIBM POWER, 和 System/360则采用大端字节序。另外,网络协议通常也会规定其所采用的字节序,还有像java这样的语言,也是规定了字节序的(tcp/ip和java都是采用大端字节序)。


通常,系统中会提供ntohs、htons、ntohl、htonl这4个函数,已实现16位和32位本地字节序和网络字节序的转换。但是,目前好像还没有提供64位数据字节序的转换函数。所以,在这里自己动手写一个。


首先,我们要判断本地系统所采用的字节序:

  1. #define BigEndian 1  
  2. #define LittleEndian 0  
  3. static bool BigEndianTest()  
  4. {  
  5.     /*定义一个2个字节长度的数据,并赋值为1,则n的16进制表示为0x0001 
  6.     如果系统以“大端”存放数据,也即是以MSB方式存放,那么低字节存放的必定是0x00,高字节存放的必定是0x01 
  7.     如果系统以“小端”存放数据,也即是以LSB方式存放,那么低字节存放的必定是0x01,高字节存放的必定是0x00 
  8.     所谓MSB,就是将最重要的位存入低位,而LSB则是将最不重要的位存入低位 
  9.     我们可以通过检测低位的数值就可以知道系统的字节序 
  10.     */  
  11.     const __int16 n = 1;  
  12.     if(*(char *)&n)  
  13.     {  
  14.         return LittleEndian;  
  15.     }  
  16.     return BigEndian;  
  17. }  
 

当然这里可以再优化一下,写成宏定义。

 

然后,定义16、32、64位的调位函数。这里就是字节“搬家”而已。

  1. #define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))  
  2. #define Swap32(l) (((l) >> 24) | /  
  3.            (((l) & 0x00ff0000) >> 8)  | /  
  4.            (((l) & 0x0000ff00) << 8)  | /  
  5.            ((l) << 24))  
  6. #define Swap64(ll) (((ll) >> 56) |/  
  7.                     (((ll) & 0x00ff000000000000) >> 40) |/  
  8.                     (((ll) & 0x0000ff0000000000) >> 24) |/  
  9.                     (((ll) & 0x000000ff00000000) >> 8)    |/  
  10.                     (((ll) & 0x00000000ff000000) << 8)    |/  
  11.                     (((ll) & 0x0000000000ff0000) << 24) |/  
  12.                     (((ll) & 0x000000000000ff00) << 40) |/  
  13.                     (((ll) << 56)))  
 

最后,

  1. #define BigEndian_16(s) BigEndianTest() ? s : Swap16(s)  
  2. #define LittleEndian_16(s) BigEndianTest() ? Swap16(s) : s  
  3. #define BigEndian_32(l) BigEndianTest() ? l : Swap32(l)  
  4. #define LittleEndian_32(l) BigEndianTest() ? Swap32(l) : l  
  5. #define BigEndian_64(ll) BigEndianTest() ? ll : Swap64(ll)  
  6. #define LittleEndian_64(ll) BigEndianTest() ? Swap64(ll) : ll  
 

现在,我们来测试一下:

 

  1. int main()  
  2. {  
  3.     unsigned __int16 i16 = 0xabcd;  
  4.     unsigned __int32 i32 = 0x0a0b0c0d;  
  5.     unsigned __int64 i64 = 0x0102030405060708;  
  6.     printf("System is %s/n",BigEndianTest() ? "BigEndian" : "LittleEndian" );  
  7.     printf("__int16 i16 = 0x%x, BigEndian:0x%x htons:0x%x, LittleEndian:0x%x ntohs:0x%x/n",  
  8.                     i16,BigEndian_16(i16),htons(i16),LittleEndian_16(i16),ntohs(BigEndian_16(i16)));  
  9.     printf("__int32 i32 = 0x%x, BigEndian:0x%x htons:0x%x, LittleEndian:0x%x ntohs:0x%x/n",  
  10.                     i32,BigEndian_32(i32),htonl(i32),LittleEndian_32(i32),ntohl(BigEndian_32(i32)));  
  11.     printf("__int64 i64 = 0x%llx, BigEndian:0x%llx, LittleEndian:0x%llx/n",i64,  
  12.                     BigEndian_64(i64),LittleEndian_64(i64));  
  13.     getchar();  
  14.     return 0;  
  15. }  
 

运行结果如下:

 

  1. System is LittleEndian  
  2. __int16 i16 = 0xabcd, BigEndian:0xcdab htons:0xcdab, LittleEndian:0xabcd ntohs:0  
  3. xabcd  
  4. __int32 i32 = 0xa0b0c0d, BigEndian:0xd0c0b0a htons:0xd0c0b0a, LittleEndian:0xa0b  
  5. 0c0d ntohs:0xa0b0c0d  
  6. __int64 i64 = 0x102030405060708, BigEndian:0x807060504030201, LittleEndian:0x102  
  7. 030405060708 
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(1442) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kelsel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值