大小端問題

工作中會遇到數據大小端問題,也就是大於1個字節的數據在內存中是怎麼存放的(內存是按字節來存放數據的,每個內存地址只放1個字節)。

大小端解釋:

大端:低地址放高位數據,高地址放低位數據

小端:低地址放低位數據,高地址放高位數據

總結一句話:按內存地址增長的順序,先放高位就據就是大端,先放低位數據就是小端。


比如32bit的CPU:

讀數據:(假設內存0x00000000,0x00000001,0x00000002,0x00000003四個地址分別存放:0xaa,0xbb,0xcc,0xdd四個字節)

大端讀出來的結果是:0xaabbccdd

小端讀出來的結果是:0xddccbbaa


存數據:(假設要把0xaabbccdd存放到0x00000000地址)

大端寫入的結果是:0x00000000(0xaa) 0x00000001(0xbb) 0x00000002(0xcc) 0x00000003(0xdd)

小端寫入的結果是:0x00000000(0xdd) 0x00000001(0xcc) 0x00000002(0xbb) 0x00000003(0xaa)


PS:X86是小端的,KEIL C51是大端的,ARM DSP是小端的,有些ARM大小端可配置的。


幾種判斷大小端的程序:

linux操作系統對大小端的判斷

static union { char c[4]; unsigned long l; } endian_test = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
(如果ENDIANNESS=’l’表示系統爲little endian,爲’b’表示big endian )。

C語言判斷

/* 1 : little-endian */

/* 0 : big-endian */

int islittle_endian() 
{
union w { int a; char b; } c;
c.a = 1;
return (c.b);
}


由於網絡字節序是大端的,此時對於大端的處理器,字節序是不需要改變的。而對於小端的處理器則需要轉變。

#if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)  
  
  
   #define htons(A)  (A)  
   #define htonl(A)  (A)  
   #define ntohs(A)  (A)  
   #define ntohl(A)  (A)  
  
  
#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)  
  
  
   #define htons(A)  ((((uint16_t)(A) & 0xff00) >> 8 ) | \\  
                      (((uint16_t)(A) & 0x00ff) << 8 ))  
   #define htonl(A)  ((((uint32_t)(A) & 0xff000000) >> 24)  | \\  
                      (((uint32_t)(A) & 0x00ff0000) >> 8 )  | \\  
                      (((uint32_t)(A) & 0x0000ff00) << 8 )  | \\  
                      (((uint32_t)(A) & 0x000000ff) << 24))  
   #define ntohs     htons  
   #define ntohl     htohl  
  
  
#else  
  
  
   #error Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both.  
  
  
#endif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章