1. 程式人生 > >大端位元組序和小端位元組序

大端位元組序和小端位元組序

對錶示一個物件的位元組序列排序,有兩個通用的規則。有些機器選擇在儲存器中按照從最低有效位元組到最高有效位元組的順序儲存物件,而另一些機器按照從最高有效位元組到最低有效位元組的順序儲存。前一種規則——最低有效位元組在最前面的 方式稱為小端法(little endian)。大多數源自以前的Digital Equipment公司(現在是Compaq公司的一部分)的機器,以及Intel的機器都採用這種規則。後一種規則(最高有效位元組在前面的方式)被稱為大端法(big endian)。IBM、Motorola和Sun Microsystems 到大多數機器都採用這種規則。注意我們說的“大多數”。這些規則並沒有嚴格按照企業界限來劃分。(摘自《深入理解計算機系統》)

假設變數x的型別為int,位於地址0x100處,有一個十六進位制的數0x12345678(高位為0x12,低位為0x78).地址範圍為0x100·0x103的位元組順序依賴於機器的型別:

令人吃驚的是在哪種位元組順序是合適的這個問題上,人們表現的非常情緒化。實際上,術語"little endian(小端)"和"big endian(大端)"來自於Jonathan Swift的《格列佛遊記》,其中交戰的兩個派別無法就應該從哪一端——小端還是大端——開啟一個半熟的雞蛋達成一致。就像雞蛋的問題一樣,沒有技術原因來選擇位元組順序規則,因此爭論退化成為關於社會政治論題的口角。對於哪種位元組排序的選擇是任意的。(摘自深入理解計算機系統)

對於大多數的應用程式設計師來說,他們機器的位元組順序是完全不可見的。無論哪種機器所編譯的程式都會得到同樣的結果,不過有時候,位元組順序會成為問題。首先是在不同型別機器之間通過網路傳送二進位制資料時。一個常見的問題是當小端法機器產生的資料被髮送到大端法機器或者反之時,接收程式會發現,字裡的位元組成了反序的。為了避免這類問題,網路應用程式的程式碼編寫必須遵守已建立的關於位元組順序的規則,以確保傳送方機器將它的內部表示轉換成網路標準,而接收方機器則將網路標準轉換為它的內部表示。(摘自深入理解計算機系統)

今天我來實現一下如何證明自己的機器採用了哪種位元組順序:

第一種方法:

/* 確定你的電腦是大端位元組序還是小端位元組序 */
#include <stdio.h>

int check1()
{
	int i = 1; //1在記憶體中的表示: 0x00000001
	char *pi = (char *)&i; //將int型的地址強制轉換為char型
	return *pi == 0; //如果讀取到的第一個位元組為1,則為小端法,為0,則為大端法
}

int main()
{
	if (check1() == 1)
		printf("big\n");
	else
		printf("little\n");

	return 0;
}

第二種方法,我們用聯合結構解決,其本質差異不大
/* 確定你的電腦是大端位元組序還是小端位元組序 */
#include <stdio.h>

int check2()
{
	union test {
		char ch;
		int i;
	}test0;
	test0.i = 1;
	return test0.ch == 0;
}
int main()
{
	if (check1() == 1)
		printf("big\n");
	else
		printf("little\n");

	return 0;
}

因為聯合結構中的變數共用一塊儲存空間,所以ch和i擁有同一個地址:

對本例中的聯合結構,我們對它求sizeof(test0),會發現它的大小為4,取了int 的大小。

關於union,我們說了,它裡邊的變數共用一塊儲存空間,但是它的大小並不總是其中最大的變數所佔的空間,還需要考慮對齊!

比如:

union test1 {

char[5];

int i;

}

它的大小就是 8 了!