首先看下图:(图片从《Unix Network Programming》copy)
对于跨越多字节的程序对象,必须确定(1)对象的地址和(2)这些字节在存储器中如何排序。
对于第一个问题,多字节对象一般被存储为连续的字节序列,对象的地址就是该对象所占字节序列中地址最小的那个字节的地址。
对于第二个问题,将最低有效字节放在低地址,最高有效字节放在高地址,这种方式称为小端法;反之,则为大端法。例如,对于一个int x = 0x01234567,地址为0x100~0x103,采用小端法和大端法的举起存储顺序如下图:
上面是对寻址和字节序的介绍,下面要什么时候要去考虑字节序:
机器使用的字节序对于大多数程序员来说是完全不可见的,无论哪种机器(无论该机器采用大端法还是小端法)编译的程序都会得到同样的结果。(这里所说的“不可见”说的通俗一点就是程序员不用去考虑字节序)。但是,下面三种情况就必须清楚机器采用的字节序。
a) 不同类型的机器之间通过网络传递二进制数据时,当小端法机器和大端法机器之间传递数据时,接收方接收到的字节就是反序的。但是网络上通信的两台机器并不知道对方采用的是大端法还是小端法,这样接收方就无法确定自己接受的字节的排列顺序。为此,网络协议指定了字节序。例如,TCP/IP协议栈采用大端字节序,因此有时要在主机字节序和网络字节序之间进行转换。(具体请看《Unix Network Programming》点击打开链接)
b) 当阅读表示整数数据的字节序列时字节顺序很重要。通常在检查机器级程序时会出现这种情况。(学习反汇编器的使用。。。。。《深入理解计算机系统》第三章有介绍点击打开链接)
c) 当编写规避正常的类型系统的程序时。C语言中的强制类型转换。
编写程序查看自己的机器采用的何种字节序列:
#include<stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, int len)
{
int i;
for(i = 0; i < len; i ++)
printf(" %.2x",start[i]);
printf("\n");
}
void show_int(int x)
{
show_bytes((byte_pointer) &x, sizeof(int));
}
int main()
{
int x = 0x01234567;
show_int(x);
return 0;
}
xx@ubuntu:~/Workspace$ gcc byteSequence.c -o byteSequence
xx@ubuntu:~/Workspace$ ./byteSequence
67 45 23 01
由此可见我的机器采用的是小端法。