大端与小端

大端与小端
一、术语来源
这两个术语来自于 Jonathan Swift 的《格利佛游记》其中交战的两个派别无法就应该从哪一端--小端还是大端--打开一个半熟的鸡蛋达成一致。

 


在那个时代,Swift是在讽刺英国和法国之间的持续冲突,Danny Cohen,一位网络协议的早期开创者,第一次 使用这两个术语来指代字节顺序,后来这个术语被广泛接纳了,成为计算机专用名词。除网络传输之外,在计算机硬件中也有使用,通常表示逻辑最小处理单元大于物理最小处理单元时逻辑单元与物理单元的映射方式。

二、大端与小端的区别
由于这个概念第一次提出时是来指代字节顺序,而且计算机物理最小处理单元通常为一个字节,所以通常情况下无论是大端还是小端都是以字节(8bit)计,在字节之内都是以大端顺序排列。但不排除以后随着计算机的发展将这个数字扩充。

字节排序含义
Big-Endian高位在前,低位在后。
Little-Endian低位在前,高位在后


请看下面这个例子:
如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12

然后,假如需要从内存中取32位整数0x1234abcd中的高16位整数,就需要知道是不是big-endian,如果是,需要从0x0002地址中去取,如果是little-endian,则需要从0x0000中取。也即怎么存就怎么取。
三、大端与小端的比较
Which is Better?

You may see a lot of discussion about the relative merits of the two formats,
mostly religious arguments based on the relative merits of the PC versus the Mac.
Both formats have their advantages and disadvantages.

In "Little Endian" form, assembly language instructions for picking up a 1, 2, 4, or longer byte number proceed
in exactly the same way for all formats: first pick up the lowest order byte at offset 0.
Also, because of the 1:1 relationship between address offset and byte number (offset 0 is byte 0),
multiple precision math routines are correspondingly easy to write.

In "Big Endian" form, by having the high-order byte come first,
you can always test whether the number is positive or negative by looking at the byte at offset zero.
You don't have to know how long the number is, nor do you have to skip over any bytes to find the byte containing the sign information.
The numbers are also stored in the order in which they are printed out, so binary to decimal routines are particularly efficient.
翻译如下:
你可能看见过很多关于这两种形式的相对优点的讨论,最激烈的争论是关于PC和MAC的相对优点。这两种形式都有其优点和缺点。

在“小终结者”形式中,提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。

在“大终结者”的形式中,靠首先提取高位字节,你总是可以由看看在偏移位置为0的字节来确定这个数字是正数还是负数。你不必知道这个数值有多长,或者你也不必跳过一些字节来看这个数值是否含有符号位。这个数值是以它们被打印出来的顺序存放的,所以从二进制到十进制的函数特别有效。
四、究竟采用何种方式?

对于不同要求的机器,在设计存取方式时就会不同。
IBM的370主机,多数基于RISC计算机,和Motorola的微处理器使用big-endian方法。TCP/IP也使用big-endian方法(big-endian方法也叫做网络编码)。对于人来说我们的语言都是从左到右的习惯方式。这看上去似乎被认为是自然的存储字符和数字方式-你同样也希望以同样的方式出现在你面前。许多人因此也会认为big-endian是流行的存储方式,正如我们平时所读到的。

然而,Intel处理器(CPUs)和DEC Alphas和至少一些在他们的平台的其他程序都是little-endian的。对于little-endian有一个问题,那就是如果你增加数字的值,你可能在左边增加数字(高位非指数函数需要更多的数字)。因此,经常需要增加两位数字并移动存储器里所有Big-endian顺序的数字,把所有数向右移,这会增加计算机的工作量。不过,使用little-endian的存储器中不重要的字节可以存在它原来的位置,新的数可以存在它的右边的高位地址里。这就意味着计算机中的某些计算可以变得更加简单和快速。
java因为存在虚拟机,所以把底层的大端和小端问题屏蔽了,内部都是小端,.net恰恰与之相反,它没有屏蔽这件事情。
五、判断大小端
C程序:

int i=1;
char *p=(char *)&i;
if(*p==1)
printf("Little Endian");
else
printf("Big Endian");

大小端存储问题,如果小端方式中(i占至少两个字节的长度)则i所分配的内存最小地址那个字节中就存着1,其他字节是0.大端的话则1在i的最高地址字节处存放,char是一个字节,所以强制将char型量p指向i则p指向的一定是i的最低地址,那么就可以判断p中的值是不是1来确定是不是小端。

一个典型面试题型:

请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1
解答:
int checkCPU( )
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return(c.b ==1);
}
}
剖析:
嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址
0x4000
0x4001
存放内容
0x34
0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址
0x4000
0x4001
存放内容
0x12
0x34
32bit宽的数0x12345678Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址
0x4000
0x4001
0x4002
0x4003
存放内容
0x78
0x56
0x34
0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址
0x4000
0x4001
0x4002
0x4003
存放内容
0x12
0x34
0x56
0x78
联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值