字節序:大端法和小端法


什么是大端法和小端法?

在幾乎所有的機器上,多字節對象都被存儲為連續的字節序列,對象的地址為所使用字節中的最小地址。

例如,假設一個類型為int的變量x的地址為0x100,即&x的值為0x100。那么x的4個字節將被存儲在
存儲器的0x100,0x101,0x102和0x103的位置。

字節序即為多字節對象存儲在內存中的字節順序,有兩種不同的存儲方案:大端法和小端法。現代的處理器大多為雙端法,大小端都支持,可以配置稱大端法或者小端法。

大端法

最高有效字節在最前面的方式稱為大端法,例如假設變量x類型為int型,位於地址0x100的地方,其16進制值為0x12345678,地址范圍為0x100到0x103字節。

對於大端法的機器來說:

0x100 0x101 0x102 0x103
12 34 56 78

由上圖可見,地址從左向右增長,x的最高有效字節12在最前面存儲。這正好和我們平時書寫習慣一致,先書寫最高有效字節,再依次寫其余字節。

小端法

最低有效字節在最前面的方式成為小端法,這正好和大端法相反,仍然用大端法中舉的例子說明:

0x100 0x101 0x102 0x103
78 56 34 12

由上圖可見,地址依然從左向右增長,x的最低有效字節在最前面存儲,與大端法相反。

如何判斷我的機器是大端法還是小端法?

在《UNIX網絡編程》上有一個程序可以判斷一個機器是大端法還是小端法,我稍加改造了一下:

#include<stdio.h>
#include<stdlib.h>

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("大端法\n");
	else if (un.c[0] == 2 && un.c[1] == 1)
		printf("小端法\n");
	else
		printf("不能判斷\n");
    } else
	printf("sizeof(short) = %d\n", sizeof(short));

    exit(0);
}

大端法和小端法對程序員有什么影響?

多數程序員不必關系所使用的機器是大端法還是小端法,在大多數情況下都不會出問題,但在某些特殊情況下這有可能成為問題:

1.編寫網絡程序時,主機之間通過網絡相互通信,不同主機之間可能采用不同的方法,而且網絡字節序和主機字節序也可能不同。

當小端法機器產生的數據被發送到大端法機器或者反方向發送時會發現接受程序子里面的字節成了反序的。為了避免這種情況的發

生,規定網絡應用程序在將數據發送之前現將數據轉換稱網絡字節序,在接收主機那邊,主機再將網絡字節序的數據轉換成適合本

主機的主機字節序,從而避免了字節序異常。(網絡字節序為大端法)

網絡編程中常用的轉換函數有如下幾個:

uing16_t htons(uint16_t host16bitvalue);    // 參數為16位主機字節序的值,返回值是16位網絡字節序的值

uint32_t htonl(uint32_t host32bitvalue);    // 參數為32位主機字節序的值,返回值是32位網絡字節序的值

uint16_t ntohs(uint16_t net16bitvalue);     // 參數為16位網絡字節序的值,返回值是16位主機字節序的值

uint32_t ntohl(uint32_t net32bitvalue);     // 參數為16位網絡字節序的值,返回值是16位主機字節序的值

2.當調試程序時常常需要將程序編譯成匯編形式,當閱讀匯編代碼時數據的字節序很重要,需要根據自己的機器是大端法還是小

端法來不同對待,以免搞錯字節順序。

3.當編寫規避正常類型系統的程序時,在C語言中可以使用強制類型轉換來允許以一中類型引用一個對象,而這種數據類型與創建

這個對象時定義的數據類型不同,大多數應用編程都不推薦這種編碼技巧,但是它們對於系統級編程來說十分有用。

參考資料:

《深入理解計算機系統》2nd

《UNIX網絡編程 卷一》3th


免責聲明!

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



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