C语言和大小端模式

在操作系统中数据长度的单位有:字节、字、双字、四字(不包括浮点型)。
比如在VC6.0的windef.h中定义了BYTE、WORD、DWORD这些类型:

typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef unsigned long       DWORD;
当然四字类型可以定义为:
typedef unsigned long long  DDWORD;


大小端模式就和CPU对字、双字、四字的存储方式有关了。
大端模式(Big-Endian):字数据的高字节存储在低地址中,字数据的低字节存储在高地址中。
小端模式(Little-Endian):字数据的高字节存储在高地址中,字数据的低字节存储在低地址中。

===以下引用自百度百科===
为什么会有大小端模式之分呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
===============

在x86或ARM架构CPU的系统上(小端模式),假设有一个WORD型变量a值为0x2010,如果将它复制到一个BYTE型的数组b中:
WORD a;
BYTE b[2];
a = 0x2010;
memcpy(b, &a, 2);

假设变量a内存地址从0x0000开始,变量a存储为:

内存地址 0x0000 0x0001
存放内容 0x10 0x20

假设数组b内存地址从0x1000开始,数组b存储为:

内存地址 0x1000 0x1001
存放内容 0x20 0x10

用memcpy复制后,b[0]=0x20,b[1]=0x10,与a相比第一个字节和第二个字节颠倒了。由于在小端模式下取WORD型变量a的值时,先取高地址中的值,复制到b[0]中。

现在变量a值变为0,b[0]=0x12,b[1]=0x34,将数组b的两个字节复制到WORD型变量a中:
WORD a=0;
BYTE b[2];
b[0]=0x12;
b[1]=0x34;
memcpy(&a, b, 2);

假设数组b内存地址从0x1000开始,数组b存储为:

内存地址 0x1000 0x1001
存放内容 0x12 0x34

假设变量a内存地址从0x0000开始,变量a存储为:

内存地址 0x0000 0x0001
存放内容 0x12 0x34

由于memcpy直接对地址进行操作,从数组b的起始地址复制了2个字节到变量a的起始地址,所以a的内存排列和b一样,但是取a的值为0x3412。

参考资料:
http://blog.163.com/yoshine@126/blog/static/607558152010918305275/