字节序(大端和小端)
为什么会存在字节序差异
-
不同cpu厂商,不同操作系统厂商各自对数据存储实现的差异(优先实现自己家的业务而忽略其他厂商),最后统一的时候发现了差异。
-
不同的CPU上运行不同的操作系统,字节序也是不同的
处理器 操作系统 字节排序 Alpha 全部 Little endian HP-PA NT Little endian HP-PA UNIX Big endian Intelx86 全部 Little endian <-----x86系统是小端字节序系统 Motorola680x() 全部 Big endian MIPS NT Little endian MIPS UNIX Big endian PowerPC NT Little endian PowerPC 非NT Big endian <-----PPC系统是大端字节序系统 RS/6000 UNIX Big endian SPARC UNIX Big endian IXP1200 ARM核心 全部 Little endian 注:数据来源于百度百科
-
不论任何cpu厂家,还是任何操作系统,数据存储都是按照字节进行存储的
-
从软件的角度上,不同端模式的处理器进行数据传递时必须要考虑端模式的不同。如进行网络数据传递时,必须要考虑端模式的转换。
-
处理器在硬件上由于端模式问题在设计中有所不同。从系统的角度上看,端模式问题对软件和硬件的设计带来了不同的影响,当一个处理器系统中大小端模式同时存在时,必须要对这些不同端模式的访问进行特殊的处理。
有哪些字节序
-
小端字节序(LE):将低序字节存储在起始地址(数据的低位字节序的内容放在高地址处,高位字节序存的内容放在低地址处)
-
大端字节序(BE):将高序字节存储在起始地址(数据的低位字节序内容存放在低地址处,高位字节序的内容存放在高地址处)
-
网络字节序(本质是BE)
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。 -
举例说明
a. 距离0x12345678的存储方式字节序 0 1 LE 0x34 0x12 BE 0x12 0x34 b. 举例0x12345678的存储方式
字节序 0 1 2 3 LE 0x78 0x56 0x34 0x12 BE 0x12 0x34 0x56 0x78
不同字节序如何转换
-
判断当前大小端
bool IsBigEndian(){ union NUM{ int a; char b; }num; num.a = 0x1234; if( num.b == 0x12 ){ return true; } return false; }
-
双字节(16位数)的大小端转换
template<typename T> int16_t translate(const T& v) { return ((v >> 8) & 0x00ff) | ((v << 8) & 0xff00); }
-
4字节(32位数)的大小端转换
template<typename T> int32_t translate(const T& t){ return (t >> 24 & 0x000000ff | t >> 8 & 0x0000ff00 | \ t << 8 & 0x00ff0000 | t << 24 & 0xff000000); }
-
通用转换方法
const char* translate(const char *tmp, size_t len){ char* ret = new char[len] {}; for (int i = 0; i < len; ++i) ret[len - 1 - i] = tmp[i]; return ret; }
-
网络字节序与主机字节序之间的转换
htons
把unsigned short类型从主机序转换到网络序htonl
把unsigned long类型从主机序转换到网络序ntohs
把unsigned short类型从网络序转换到主机序ntohl
把unsigned long类型从网络序转换到主机序
注意事项
- 大端小端只是CPU的处理方式,UTF-16的编码单位是两字节,也就是CPU同时处理两字节,所以需要考虑大小端。 UTF-8的编码单位是1字节,CPU一次只处理一个字节,就不需要考虑大小端。
- 大端和小端存储方式只是在多字节数据类型的字节顺序方面有所不同。在实际应用中,选择使用哪种存储方式取决于特定的硬件架构和协议要求。
本文来自博客园,作者:flxx,转载请注明原文链接:https://www.cnblogs.com/faithlocus/p/16768095.html