现在的位置: 首页 > 综合 > 正文

大小端问题

2013年12月02日 ⁄ 综合 ⁄ 共 1611字 ⁄ 字号 评论关闭

啊~大小端的内存分布搞不清楚-_-~平时用得少也忘了,今天在这里重温复习一下吧。

1.大小端的起源以及区别

端模式出自Jonathan Swift书写的《格列佛游记》。这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为Big Endian,从尖头开始将鸡蛋敲开的人被归为Littile Endian。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开。在计算机业Big Endian和Little Endian也几乎引起一场战争。在计算机业界,Endian表示数据在存储器中的存放顺序。下文举例说明在计算机中大小端模式的区别。

如果将一个32位的整数0x12345678 存放到一个整型变量(int)中,这个整型变量采用大端或者小端模式在内存中的存储由下表所示。为简单 起见,本文使用OP0表示一个32位数据的最高字节MSB(Most Significant Byte),使用OP3表示一个32位数据最低字节LSB(Least Significant Byte)。

地址偏移

大端模式

小端模式

0x00

12(OP0)

78(OP3)

0x01

34(OP1)

56(OP2)

0x02

56(OP2)

34(OP1)

0x03

78(OP3)

12(OP0)

如果将一个16位的整数0x1234存放到一个短整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示。

地址偏移

大端模式

小端模式

0x00

12(OP0)

34(OP1)

0x01

34(OP1)

12(OP0)

那天就是这个顺序弄乱了··现在看起来太畸形了 有木有 有木有!抓狂

大端:高位存在低地址,低位存在高地址。

小端:高位存在高地址,低位存在低地址。 (intel的x86,ARM普遍都是属于小端)。

2.判断大小端

这个就得用联合体了.

union w
{  
    int  a;
    char b;
} c;

printf("0X%0x\n",&c);    //保存在0x0012FE8C
printf("0X%0x\n",&c.a);  //保存在0x0012FE8C
printf("0X%0x\n",&c.b);  //保存在0x0012FE8C
c.a = 0x00000001;
return(c.b ==1); //小端为true,大端为false

int a为1,即0x00000001时;低位存在内存低地址中,01存在 0x0012FE8C中,其余三个00分别存放在0x0012FE8D0x0012FE8E0x0012FE8F中。

3.练习

画出下面这个结构体的内存分布情况···我直接打印了出来。

struct  
{
   char c1;
   char c2;
   int i;
}str;
int main()
{
   str.c1=2;
   str.c2=16;
   str.i=1234;
   printf("0X%0x 0x%02x\n",&str.c1,*(&str.c1));
   printf("0X%0x 0x%02x\n",&str.c2,*(&str.c2));
   printf("0X%0x 0x%02x\n",&str.c2+1,*(&str.c2+1));
   printf("0X%0x 0x%02x\n",&str.c2+2,*(&str.c2+2));
   printf("0X%0x 0x%02x\n",&str.c2+3,*(&str.c2+3));
   printf("0X%0x 0x%02x\n",&str.c2+4,*(&str.c2+4));
   printf("0X%0x 0x%02x\n",&str.c2+5,*(&str.c2+5));
   printf("0X%0x 0x%02x\n",&str.c2+6,*(&str.c2+6));
   return 0;
}

如图可见,1234的十六进制数0X04D2在内存中分布为:低位0XD2在内存低地址0X417168中,高位0X04在内存高地址0X417169中,可知该测试程序是在小端中运行。

    

抱歉!评论已关闭.