数字的大小端转换

简介

在不同的系统中,当最最基础的数据存在问题的时候,这是最让人头疼的问题。但是,世界就是爱和我们开玩笑,不是么?在芯片中,有两种方式存储数据:

  • 大端,也叫Big-Endian,同样有个很感人的名字Motorola
  • 小端,也叫little-Endian,同样也有一个和我们息息相关的名字Intel
    至于,为什么这么叫,具体的自己去查找。

用在什么场合?

一般小端,会用在数据的存储上,而大端用在数据的传输。前者也叫主机序,后者也叫网络字节序,当然,也不是绝对。至于用什么,当然根据自己的爱好了,当然和协议也有很大的关系。

如何把主机上的数据通过网络传输?

这其中,涉及到很多问题,主机序列是否和网络字节序匹配,这里,分开说明。

主机字节序和网络字节序相同

  • 准备工作

     //type define uchar(8bit) & uword(16bit) & uint(32)
     typedef unsigned char uchar;
     typedef unsigned short uword;
     typedef unsigned int uint;
     //Network data buffer
     #define BUFFER	(0x08)
     //data receved buffer
     uchar data[BUFFER];
     //data
     uint num;
    
  • 转换代码,如果转换为uint型:
    - 接收
    Value = *(uint*)&data[0];
    - 发送
    data[0] = *(uchar*)#

如果存在差异

可以利用如下的宏来进行转换

#define lit_big_TransShort(a_data) (((a_data) & 0x00ff) << 8 | ((a_data) & 0xff00) >> 8)
#define lit_big_TransLong(a_data) (((a_data) & 0xff000000) >> 24 | ((a_data) & 0x000000ff) << 24)
#define lit_big_TransWord(a_data) lit_big_TransShort(a_data)
#define lit_big_TransInt(a_data)  (lit_big_TransLong(a_data) | (lit_big_TransShort((a_data) >> 8) << 8))
  • 如果有差异,可以经过以下两个步骤:
  1. Value = *(uint*)&data[0];
  2. Value = lit_big_TransInt(Value);
  • 或者
  1. num = lit_big_TransInt(num);
  2. data[0] = *(uchar*)&num;

以上的方式在某些地方存在问题,正如上一篇文章描述的问题:

某些芯片,由于架构的原因,并不支持奇数地址指针的某些数据获取。所以,如果通过这种暴力的指针类型转换是存在问题的,所以,只有提供如下的函数来进行转换。

最好的解决办法,就是自己编写一个类似于网络字节序转主机字节序的函数。
以下是这几个函数:

  • htons()
  • htonl()
  • ntohs()
  • ntohl()
    记忆规则就是“h/n”表示host or Network,加上to这个向量标识,"s/l"表明转换大小:short/long.
posted @ 2016-05-24 22:17  ply616  阅读(3457)  评论(0编辑  收藏  举报