數字的大小端轉換


簡介

在不同的系統中,當最最基礎的數據存在問題的時候,這是最讓人頭疼的問題。但是,世界就是愛和我們開玩笑,不是么?在芯片中,有兩種方式存儲數據:

  • 大端,也叫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.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM