1. 程式人生 > >大端、小端轉換

大端、小端轉換

大端、小端轉換

http://oss.org.cn/kernel-book/ldd3/ch11s04.html

小心不要假設位元組序. PC 儲存多位元組值是低位元組為先(小端為先, 因此是小端), 一些高階的平臺以另一種方式(大端)工作. 任何可能的時候, 你的程式碼應當這樣來編寫, 它不在乎它操作的資料的位元組序. 但是, 有時候一個驅動需要使用單個位元組建立一個整型數或者相反, 或者它必須與一個要求一個特定順序的裝置通訊.

包含檔案 <asm/byteorder.h> 定義了或者 __BIG_ENDIAN 或者 __LITTLE_ENDIAN, 依賴處理器的位元組序. 當處理位元組序問題時, 你可能編碼一堆 #ifdef __LITTTLE_ENDIAN 條件語句, 但是有一個更好的方法. Linux 核心定義了一套巨集定義來處理之間的轉換, 在處理器位元組序和你需要以特定位元組序儲存和載入的資料之間. 例如:

u32 cpu_to_le32 (u32);

e32_to_cpu is used for convesions from 32bit little endian data into CPUs endianness

u32 le32_to_cpu (u32);

cpu_to_le32 is used for convesions from CPU endianness to little endian 32bit data.

這 2 個巨集定義轉換一個值, 從無論 CPU 使用的什麼到一個無符號的, 小端, 32 位數, 並且轉換回. 它們不管你的 CPU 是小端還是大端, 不管它是不是 32-位 處理器. 在沒有事情要做的情況下它們原樣返回它們的引數. 使用這些巨集定義易於編寫可移植的程式碼, 而不必使用大量的條件編譯建造.

有很多類似的函式; 你可以在 <linux/byteorder/big_endian.h> 和 <linux/byteorder/little_endian.h> 中見到完整列表. 一會兒之後, 這個模式不難遵循. be64_to_cpu 轉換一個無符號的, 大端, 64-位 值到一個內部 CPU 表示. le16_to_cpus, 相反, 處理有符號的, 小端, 16 位數. 當處理指標時, 你也會使用如 cpu_to_le32p, 它使用指向一個值的指標來轉換, 而不是這個值自身. 剩下的看包含檔案.

可以使用下面的方法來判斷處理器使用的什麼模式

    int GetEndianness()  
    {  
       short s = 0x0110;  
       char *p = (char *) &s;  
       if (p[0] == 0x10)  
          return 0;// 小端格式  
       else  
          return 1;// 大端格式  
    }