啊~大小端的内存分布搞不清楚-_-~平时用得少也忘了,今天在这里重温复习一下吧。
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分别存放在0x0012FE8D、0x0012FE8E和0x0012FE8F中。
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中,可知该测试程序是在小端中运行。