大端和小端


一、簡述

1.1大端小端區別

  • 根據計算機中數據在硬件(內存/寄存器)中存儲順序(存儲方式),可以分為大端小端
  • 大端:低地址存儲高位數據。
  • 小端:低地址存儲低位數據。

舉例:0x123456在內存中的存儲方式

  1 - 大端模式:
  2 低地址 -----> 高地址
  3 0x12 | 0x34 | 0x56
  4 
  5 
  6 - 小端模式
  7 低地址 -----> 高地址
  8 0x56 | 0x34 | 0x12


1.2大端小端來源

端模式(Endian)的這個詞出自JonathanSwift書寫的《格列佛游記》。這本書根據將雞蛋敲開的方法不同將所有的人分為兩類,從圓頭開始將雞蛋敲開的人被歸為BigEndian,從尖頭開始將雞蛋敲開的人被歸為LittileEndian。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開。在計算機業BigEndian和LittleEndian也幾乎引起一場戰爭。在計算機業界,Endian表示數據在存儲器中的存放順序。

  • 一開始是由於不同架構的CPU處理多個字節數據的順序不一樣,比如x86的是小段模式,KEIL C51是大端模式。但是后來互聯網流行,TCP/IP協議規定為大端模式,為了跨平台通信,還專門出了網絡字節序和主機字節序之間的轉換接口(ntohs、htons、ntohl、htonl)
  • 大小端模式各有優勢:小端模式強制轉換類型時不需要調整字節內容,直接截取低字節即可;大端模式由於符號位為第一個字節,很方便判斷正負。

1.3大端、小端設備

  • 互聯網使用的網絡字節順序采用大端模式進行編址,而主機字節順序根據處理器的不同而不同。
  • 大端模式處理器的字節序到網絡字節序不需要轉換;而小端模式處理器的字節序到網絡字節必須要進行轉換。
小端設備 大端設備
Pentuim處理器 PowerPC處理器
x86機  
IBM,Motorola(PowerPC),Sun的機器  
ARM、Alpha、Motorola(PowerPC),即能工作於大端又能工作於小端,需要具體參考處理器手冊。


  • 大部分用戶的操作系統(如windows, FreeBsd,Linux)是Little Endian的。少部分是Big Endian,如MAC OS 。Little Endian還是Big Endian與操作系統和芯片類型都有關系。
  • Linux系統中,可以在/usr/include/中(包括子目錄)查找字符串BYTE_ORDER(或_BYTE_ORDER,__BYTE_ORDER),確定其值。
  • BYTE_ORDER中文稱為字節序。這個值一般在endian.h或machine/endian.h文件中可以找到,有時在feature.h中,不同的操作系統可能有所不同。

二、判斷大端小端

原理:

  1. C/C++中short占2個字節,char占1個字節。0xFF00存入short變量。
  2. 取short變量中的一個字節數據存入char變量。
  3. 判斷char變量地址和short變量地址關系。
  4. 如果char地址比short地址更大,說明從short變量取的數據是高地址數據。
  5. 判斷char數據是0x00還是0xFF,從而判斷出當前系統是大端還是小端。

測試大端小端代碼(C++):

  1 #include <iostream>
  2 
  3 
  4 
  5 using namespace std;
  6 
  7 int main()
  8 {
  9 
 10 	int intData(0xFFFF0000);
 11 	short *shortData = (short*)(&intData);
 12 
 13 	std::cout << "intData address:\t";
 14 	std::cout << &intData << endl;
 15 
 16 	std::cout << "shortData address:\t";
 17 	std::cout << shortData << endl;
 18 
 19 	//獲取當前數據地址前一個地址數據和之后一個數據
 20 	short *low = shortData - 1;
 21 	short *high = shortData + 1;
 22 
 23 	//如果之前一個數據和之后一個數據相等,則沒有辦法判斷,此時需要重新檢測
 24 	if (*low == *high)
 25 	{
 26 		std::cout << "Please check again!\n";
 27 		getchar();
 28 		return 0;
 29 	}
 30 
 31 	//臨時short變量和其地址內容比較使用
 32 	//注意不能直接用0xFFFF和short直接比較,否則有時出錯,會把0xFFFF看作int比較
 33 	short temp = 0xFFFF;
 34 
 35 	//當前地址的內容是高位數據
 36 	if (*shortData == temp)
 37 	{
 38 		temp = 0x0000;
 39 		//*shortData地址是高位地址
 40 		if (*low == temp)
 41 		{
 42 			std::cout << "otherPartData addr:\t";
 43 			std::cout << low << endl;
 44 			std::cout << "====================" << endl;
 45 
 46 			std::cout << "shortData is:\t\t";
 47 			std::cout << hex << *shortData << endl;
 48 			std::cout << "otherPartData is:\t";
 49 			std::cout << hex << *low << endl;
 50 			std::cout << "====================" << endl;
 51 
 52 			std::cout << "Little endian!\n";
 53 		}
 54 		//*shortData地址是低位地址
 55 		if (*high == temp)
 56 		{
 57 			std::cout << "otherPartData addr:\t";
 58 			std::cout << high << endl;
 59 			std::cout << "====================" << endl;
 60 
 61 			std::cout << "shortData is:\t\t";
 62 			std::cout << hex << *shortData << endl;
 63 			std::cout << "otherPartData is:\t";
 64 			std::cout << hex << *high << endl;
 65 			std::cout << "====================" << endl;
 66 
 67 			std::cout << "Big endian!\n";
 68 		}
 69 	}
 70 	//當前地址存儲低位數據
 71 	else
 72 	{
 73 		temp = 0xFFFF;
 74 		//*shortData地址是高位地址
 75 		if (*low == temp)
 76 		{
 77 
 78 			std::cout << "otherPartData addr:\t";
 79 			std::cout << low << endl;
 80 			std::cout << "====================" << endl;
 81 
 82 			std::cout << "shortData is:\t\t";
 83 			std::cout << hex << *shortData << endl;
 84 			std::cout << "otherPartData is:\t";
 85 			std::cout << hex << *low << endl;
 86 			std::cout << "====================" << endl;
 87 
 88 			std::cout << "Big endian!\n";
 89 		}
 90 		//*shortData地址是低位地址
 91 		if (*high == temp)
 92 		{
 93 			std::cout << "otherPartData addr:\t";
 94 			std::cout << high << endl;
 95 			std::cout << "====================" << endl;
 96 
 97 			std::cout << "shortData is:\t\t";
 98 			std::cout << hex << *shortData << endl;
 99 			std::cout << "otherPartData is:\t";
100 			std::cout << hex << *high << endl;
101 			std::cout << "====================" << endl;
102 
103 			std::cout << "Little endian!\n";
104 		}
105 	}
106 	getchar();
107 	return 0;
108 
109 }


Window系統運行結果:

  1 intData address:        010FFE70
  2 shortData address:      010FFE70
  3 otherPartData addr:     010FFE72
  4 ====================
  5 shortData is:           0
  6 otherPartData is:       ffff
  7 ====================
  8 Little endian!
  9 




三、相關參考


免責聲明!

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



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