大端和小端

  • 格式:docx
  • 大小:53.39 KB
  • 文档页数:4

一、大段模式和小端模式

大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;

小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。

二、为什么会有大小端模式

在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为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处理器还可以由硬件来选择是大端模式还是小端模式。

三、大小端在内存中的存放方式举例

16bit宽的数0x1234

在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 0x4001 0x4002

存放内容 0x34 0x12

而在Big-endian模式CPU内存中的存放方式则为:

内存地址 0x4001 0x4002

存放内容 0x12 0x34

32bit宽的数0x12345678

在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址 0x4001 0x4002 0x4003 0x4004

存放内容 0x78 0x56 0x34

0x12

在Big-endian模式CPU内存中的存放方式则为:

内存地址 0x4001 0x4002 0x4003 0x4004

存放内容 0x12 0x34 0x56 0x78

四,有关大小端的习题

题目:在x86系统下,其值为多少?

int main()

{

int a[4]={1,2,3,4};

int *ptr1=(int*)(&a+1);

int *ptr2=(int*)((int)a+1);

print ("%x,%x",prt1[-1],*ptr2);

return 0;

}

先说ptr1,我知道&a是整个数组的首地址,所以&a+1指到了整个数组后面。因为(&a+1)这个地址转换成(int*),所以(a&+1)指向了整个数组后一个int型的整数。prt1[-1]就是

*(prt1-1),也就是a[3],所以是4。

再说ptr2,a表示数组首元素的首地址,(int)a+1就是把地址a转换int型加1,因为int类型是4个字节存储,(int)a+1就指向a[0]的第二个字节的指针了。转换成(int*)的ptr2就像上图表示的一样指向一个int类型,这就和大端小端存储有关系了。

大端模式

低地址高地址

a[0] a[1] a[2]

4字节 4字节

大端模式

0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x02 …

小端模式

0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00 …

在大端模式下读取的是:0x00 0x00 0x01 0x00 也就是0x100

在小端模式下读取的是:0x00 0x000x00 0x20 也就是0x2000000

五、编写程序测试机器是大端还是小端模式

方法1(推荐,简单易懂):

/* 0 is Big-endian, 1 is Little-endian */

intcheckEndian(void)

{

union check

{

intiNum;

charch;

};

union check c;

c.iNum = 1;

return (1 == c.ch);

}

方法2:

int main(void)

{

shortint x;

char x0,x1;

x=0x1122;

x0=((char *)&x)[0]; //低地址单元

x1=((char *)&x)[1]; //高地址单元

printf("x0=0x%x,x1=0x%x",x0,x1);// 若x0=0x11,则是大端; 若x0=0x22,则是小端......

return 0;

}

方法3:

typedef unsigned char byte;

// 转换char(视为整数类型)为16进制字符串

voidChtoHex(byte Val, char* dest)

{

// 辗转相除法,倒序看得到结果

bytetmp = Val % 16;

if (tmp>= 0 &&tmp<= 9)

{

dest[1] = '0' + tmp;

}

else if (tmp>= 10 &&tmp<= 15)

{

dest[1] = 'A' + tmp - 10;

}

tmp = (Val/16) % 16;

if (tmp>= 0 &&tmp<= 9)

{

dest[0] = '0' + tmp;

}

else if (tmp>= 10 &&tmp<= 15)

{

dest[0] = 'A' + tmp - 10;

}

// 设置\0

dest[2] = '\0';

}

// 主函数

void main()

{

int u = 367328153; // 原始数据,8位16进制为15 E4 FB 99

byte a, b, c, d; // u从低地址到高地址的四个字节 // a~d对应的16进制字符串,预留3个字符

char Sa[3], Sb[3], Sc[3], Sd[3];

byte* k = (byte*)&u;

a = k[0];

b = k[1];

c = k[2];

d = k[3];

// 转成16进制字符串

ChtoHex(a, Sa);

ChtoHex(b, Sb);

ChtoHex(c, Sc);

ChtoHex(d, Sd);

printf("%s %s %s %s\n", Sa, Sb, Sc, Sd);

}