判斷big endian和little endian的方法


 
不同體系的CPU在內存中的數據存儲往往存在着差異。例如,Intel的x86系列處理器將低序字節存儲在起始地址,而一些RISC架構的處理器,如IBM的370主機使用的PowerPC或Motorola公司生產的CPU,都將高序字節存儲在起始位置。這兩種不同的存儲方式被稱為little-endian和big-endian。
little-endian是x86系列CPU的數據存儲方式,即將低序的部分存儲在前面。而big-endian是將高序部分存儲在前面。例如,要存儲0xF432,little-endian將以32F4存儲,而使用big-endian與此相反,將存儲為F432,如圖13.2所示。
程序p13.1.c講解了如何判斷系統是使用big-endian還是little-endian實現數據存儲的。程序中使用的方法如下所示。
 
 
圖13.2   big-endian與little-endian方式數據存儲示例
(1)利用聯合的特點。聯合中的數據成員是共享存儲空間的,所分配的空間為數據成員中最大所需的內存數。程序定義了名為endian_un的聯合體,其中包含兩個數據成員,一個是short類型的數據成員(在32位系統上,short類型的長度是2字節),一個是字符類型的字符數組,字符數組的元素個數為short類型的字節數。
程序將var賦值為0x0102。由於聯合結構的特點,bits字符串數組中同樣存儲了0x0102這一數值。通過判斷字符串中的低位和高位存儲的內容,就可以知道系統是little-endian還是big-endian的。

#include

int main(int argc, char **argv)  {          union {            short  s;        char   c[sizeof(short)];      } un;

        un.s = 0x0102;          if (sizeof(short) == 2) {                  if (un.c[0] == 1 && un.c[1] == 2)                          printf("big-endian\n");                  else if (un.c[0] == 2 && un.c[1] == 1)                          printf("little-endian\n");                  else                          printf("unknown\n");          } else                  printf("sizeof(short) = %d\n", sizeof(short));

        exit(0);  }

 

(2)通過強制類型轉換實現。程序中通過取flag變量的地址,獲得起始空間的存儲內容。如果起始空間存儲的是數據的低位內容,則表示存儲方式為little-endian,否則為big-endian。
程序的具體代碼如下:
//使用類型的強制轉換實現little-endian與big-endian的判斷
int is_little_endian(void)
{
  unsigned short flag=0x4321;
  if (*(unsigned char*)&flag==0x21)
    return 1;
  else
    return 0;
}

使用gcc編譯p13.1.c,獲得名為p13.1的可執行文件。執行該程序,具體輸出如下。可以看到x86系統的內存數據存儲方式為little-endian方式。
[program@localhost charter13]$ gcc -o p13.1 p13.1.c 
[program@localhost charter13]$ ./p13.1 
judged by first method, little-endian
judged by second method, little-endian
[program@localhost charter13]$
之所以介紹big-endian和little-endian,是因為這一數據存儲方式不僅影響程序在不同硬件平台中的移植,而且在網絡編程中也要考慮字節順序的問題。為了避免兼容性的問題,網絡中的數據傳輸都使用了從高到低的順序存儲方式。因此,如果要將數據從低位字節優先(little-endian)的機器上發往網絡,必須首先進行轉換。而big-endian的機器是不需要轉換的。
Linux系統提供了htons、htonl、ntohs、ntoh這4個函數用於進行字節順序的轉換。其中,h是host的縮寫,n表示network。最后一個字符如果是s,表示short類型,如果是l,表示為long類型。4個函數的具體定義如下:
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
 
htonl/htons:表示主機字節順序轉換成網絡字節順序,htonl函數和htons函數的區別在於參數長度存在差異。
 
ntohl/ntohs:表示網絡字節順序轉換成主機字節順序,ntohl函數和ntohs函數的區別在於參數長度存在差異。


免責聲明!

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



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