大端和小端
一、简述
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中,不同的操作系统可能有所不同。
二、判断大端小端
原理:
- C/C++中short占2个字节,char占1个字节。0xFF00存入short变量。
- 取short变量中的一个字节数据存入char变量。
- 判断char变量地址和short变量地址关系。
- 如果char地址比short地址更大,说明从short变量取的数据是高地址数据。
- 判断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
三、相关参考
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。