谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?网络
其实big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。函数
用文字说明可能比较抽象,下面用图像加以说明。好比数字0x12345678在两种不一样字节序CPU中的存储顺序以下所示:翻译
Big Endian指针
低地址 高地址内存
----------------------------------------------------------------------------->开发
| 12 | 34 | 56 | 78 |it
Little Endian io
低地址 高地址编译
----------------------------------------------------------------------------->nio
| 78 | 56 | 34 | 12 |
从上面两图能够看出,采用big endian方式存储数据是符合咱们人类的思惟习惯的。
为何要注意字节序的问题呢?你可能这么问。固然,若是你写的程序只在单机环境下面运行,而且不和别人的程序打交道,那么你彻底能够忽略字节序的存在。可是,若是你的程序要跟别人的程序产生交互呢?尤为是当你把你在微机上运算的结果运用到计算机群上去的话。
在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则惟一采用big endian方式来存储数据。试想,若是你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的0x12345678来讲,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,因为JAVA采起big endian方式存储数据,很天然的它会将你的数据翻译为0x78563412。所以,在你的C程序传给JAVA程序以前有必要进行字节序的转换工做。
全部网络协议也都是采用big endian的方式来传输数据的。因此有时咱们也会把big endian方式称之为网络字节序。当两台采用不一样字节序的主机通讯时,在发送数据以前都必须通过字节序的转换成为网络字节序后再进行传输。ANSI C中提供了下面四个转换字节序的宏。
一道C语言的试题:请写一个C函数,若处理器是Big_endian的,则返回0;如果Little_endian的,则返回1。
解答:
int checkCPU()
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return (c.b == 1);
}
}
嵌入式系统开发者应该对Little-endian和Big-endian模式很是了解。采用Little-endian模式的CPU对操做数的存放方式是从低字节到高字节,而Big-endian模式对操做数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little- endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址
存放内容
0x4000
0x34
0x400
0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址
存放内容
0x4000
0x12
0x4001
0x34
32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址
存放内容
0x4000
0x78
0x4001
0x56
0x4002
0x34
0x4003
0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址
存放内容
0x4000
0x12
0x4001
0x34
0x4002
0x56
0x4003
0x78
联合体union的存放顺序是全部成员都从低地址开始存放,解答利用该特性,轻松地得到了CPU对内存采用Little-endian仍是Big-endian模式读写。
好比 int a = 0x05060708
在BIG-ENDIAN的状况下存放为:
字节号 0 1 2 3
数据 05 06 07 08
在LITTLE-ENDIAN的状况下存放为:
字节号 0 1 2 3
数据 08 07 06 05
----【转】