big-endian與little-endian區別

big-endian與little-endian
 
今天研究sql*loader碰到字節排序的問題順便找了相關的資料看看。
Byte order affects the results when data is written and read an even number of bytes at a time (typically 2 bytes, 4 bytes, or 8 bytes). The following are some examples of this:
  • The 2-byte integer value 1 is written as 0x0001 on a big-endian system and as 0x0100 on a little-endian system.
  • The 4-byte integer 66051 is written as 0x00010203 on a big-endian system and as 0x03020100 on a little-endian system.
Byte order also affects character data in the UTF16 character set if it is written and read as 2-byte entities. For example, the character 'a' (0x61 in ASCII) is written as 0x0061 in UTF16 on a big-endian system, but as 0x6100 on a little-endian system.
 
下面爲查找的資料
 
不一樣體系的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的。
(2)經過強制類型轉換實現。程序中經過取flag變量的地址,得到起始空間的存儲內容。若是起始空間存儲的是數據的低位內容,則表示存儲方式爲little-endian,不然爲big-endian。
程序的具體代碼以下:
    //p13.1.c 判斷big-endian與little-endian
#include <stdio.h>
//使用類型的強制轉換實現little-endian與big-endian的判斷
int is_little_endian(void)
{
unsigned short flag=0x4321;
if(*(unsigned char*)&flag==0x21)
return 1;
else
return 0;
}
int main(void)
{
//利用聯合的特色來判斷little-endian與big-endian
union endian_un{
short var;
char bits[sizeof(short)];
};
union endian_un flag;
flag.var=0x0102;
//判斷低位和高位的存儲內容,肯定是何種方式
if(sizeof(short)==2){
if(flag.bits[0]==1 && flag.bits[1]==2)
printf("judged by first method, big-endian\n");
else if(flag.bits[0]==2 && flag.bits[1]==1)
printf("judged by first method, little-endian\n");
else
printf("cannot determine the type\n");
}
if(is_little_endian())
printf("judged by second method, little-endian\n");
else
printf("judged by second method, big-endian\n");
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函數的區別在於參數長度存在差別。
相關文章
相關標籤/搜索