字节序,顾名思意,就是字节的顺序,指的是大于一个字节的数据在内存中的存储方式。字节序跟 CPU 的型号有关系。常用的字节序有两种, Big endian( 大端字节序 ) 和 Little endian( 小端字节序 ) 。 Inter 的 X86 CPU 用的都是小端字节序, IBM 的 PowerPC 用的是大端字节序。
以一个 int 型整数 0x12345678 为例, int 型在 32 位操作系统下在内存中占 4 个字节,比如说从 0x4000~0x4003 。 0x4000 是内存中的低位地址, 0x4003 为高位地址。按小端字节序存储,则在内存中分布如下:
0x4003 0x12
0x4002 0x34
0x4001 0x56
0x4000 0x78
即整数的低字节存储在内存中的低位地址中,整数的高字节存储在内存中的高位地址中。
如果按大端字节序存储,则在内存中分布如下:
0x4003 0x78
0x4002 0x56
0x4001 0x34
0x4000 0x12
即整数的低字节存储在内存中的高位地址中,整数的高字节存储在内存中的低位地址中。
在单机上运行的程序通常无需考虑字节序的问题,但如果跨平台移植或是进行网络通讯则必须考虑字节序的转换问题。常用的网络协议都是用的大端字节序,也就是常说的网络字节序。 Java 语言开发的程序用的也是大端字节序。所以在 inter x86 平台下编写的 C++ 程序与 java 程序通讯时,必须考虑字节序转换的问题。
字节对齐
请看如下两个结构体
struct Test1
{
char c ;
long a ;
short b ;
};
struct Test2
{
long a ;
short b ;
char c ;
};
读者不妨做一下测试,测试一下这两个结构体在内存中的大小。经测试 sizeof(Test1)=12, sizeof(Test2)=8 。为什么会这样呢?下面我就解释一下结构体长度是如何计算出来的。
Vc 中默认的字节对齐长度是 4 ,当然用户也可以使用预编译指示符 #prama pack(value) 指定对齐长度。结构体最终对齐长度的大小为结构体中最大的类型长度与默认(或设置)的长度中的最小值。所以, Test1 和Test2 结构体的对齐长度均为4 。即结构体中每个变量均要按照4 字节进行对齐。Test1 中变量在内存中的分布如下所示:
C 空空空
a a a a
b b 空空
累计一共12 个字节。
结构体Test2 中变量在内存中的分布如下所示:
a a a a
b b c 空
累计一共8 个字节。
总结一下,结构体对齐的规则就是:
如果最终的对齐长度是 4 字节,那么首先存储结构体中的第一个变量,如果它的长度小于 4 字节,比如说 char 类型,只需 1 个字节,那么还剩 3 个字节的空间,然后再存储第二个变量,如果第二个变量所需长度小于剩余的 3 个字节,则在 3 个字节中存储第二个变量,反之,如果第二个变量长度大于 3 字节,比如说第二个变量是 int 型,它需要 4 字节的空间,则再申请 4 字节的空间用于存储第二个变量,将刚才剩余的 3 个字节的空间填充空字节。依次类推。还有一点,就是最终结构体的长度应该是对齐长度的整数倍,不足部分补空字节。