[转]关于Endian的问题

原创 2005年04月29日 13:53:00
关于Endian的问题

这个标题中的Endian是什么意思呢?还是让我们先来看看下面的情况,这是内存中一个
WORD值中的内容,那么这个WORD中的值是0x1234呢,还是0x3412 ?

low byte high byte
0x12 0x34

熟悉x86汇编的人立刻就知道这个值应为0x3412,很对,但在一些情况下,比如说你在
SGI的机器上看到这种情况,则正好相反,0x1234才是正确答案,这与CPU内部处理数据
的方式有关。这两种处理方式都存在于不同厂商生产的CPU之中,在上例中若此WORD值
为0x3412的,我们称之为little-endian, 若为0x1234的,我们称之为big-endian,这
是两种不同的byte orders。MSDN中有比较精确的定义如下:

Byte Ordering Byte ordering Meaning
big-endian The most significant byte is on the left end of a word.
little-endian The most significant byte is on the right end of a word.

一般来说我们不用关心byte ordering的问题,但若要涉及跨平台之间的通信和资源共
享,则不得不考虑这个问题了。也许你会说,我永远不会去用其它非x86的CPU,也许是
这样,你甚至可以不必知道我们最常用的Intel,AMD等生产的x86的byte ordering是
little-endian的,而且按现在的装机数量来看,可以说世界上绝大多数CPU是
little-endian的,但多了解一些没有什么坏处,也许有用上的一天,实际若您要涉及
到网络编程,了解一些还是有所帮助的,看完本文后您就应该知道为何socket编程中为
何要用到如 ntohl, htonl, ntohs, htons这几个看起来名字似乎怪怪的API了,也很容
易理解这些函数名的意义了。

假设我们要在不同byte ordering的机器之间传输和交换数据,那该怎么办呢,有两个
方法,一是全部转换成文本来传输(如XML使用的),另一个方法两方都按照某一方的
byte order,这时就涉及到了不同byte order之间相互转换的问题(网络传输标准如
TCP/IP采用第二种方法并且由于历史的原因,byte ordering是big-endian的)。两种
之间该如何转换呢?方法有很多,我们可以先看看MFC中在处理serialize的代码中所用
的方法(List), 虽然代码应该是高效易读的, 但我个人并不喜欢它, 原因是我觉得这不
是一种通用优美的方法.下面列出的是我自己写的转换的代码:


template
F3D_INLINE T ConvertEndian(T  t)
{
T tResult = 0;
for (int  I = 0; I < sizeof(T); ++ I)
{
tResult <<= 8;
tResult |= (t & 0xFF) ;

t >>= 8;
}

return  tResult;
}

原理非常简单,交换字节顺序,我就不多说了,当然这个写法并不是快速的, 只是通用
的(我没条件试, 若有不对之处请指出), 若要快速的代码,可以在不同platform上用与
platform相关的代码, 如在PowerPC上有 "load word byte-reversed indexed"
(lwbrx) 和 "load halfword byte-reversed indexed" (lhbrx) 指令, 在x86上还可用
BSWAP单个汇编指令等,在类型上专为int16, int32写的通用的代码也可以比这快得多.

当然如果在byte ordering相同的情况下,应该不必用这个转换函数,所以我们可以定
义一个宏来处理不同的byte ordering,也可以在运行时测试byte ordering, 下面的代
码给出了一个简单的测试方法。


// Test for endianness.
F3D_INLINE bool IsLittleEndian(void)
{
DWORD dwTestValue = 0x12345678L;
return  (*((BYTE*)&dwTestValue) == 0x78);
}

但是float比较怪,有可能所涉及到不仅仅是byte order的问题,因为有些平台如Alpha
不使用IEEE的浮点格式,还得自己转换。当然同上,其它的方法一是将所用的float用
文本方式输入输出,另一个办法是在某些情况下可将其转换成定点数再处理,这里我不
再深入。

如果是读写第三方已经指定byte order的文件或数据流,比如说读SGI的位图文件格
式,则可以直接自行按指定的byte order拼起来,不必考虑host机是何种byte
ordering。下面我给出相应的代码:


// Read a little-endian TYPE from address
template
F3D_INLINE T GetLittleEndian(const BYTE*  pBuf)
{
T tResult = 0;
pBuf += sizeof(T) - 1;
for (int  I = 0; I < sizeof(T); ++ I)
{
tResult <<= 8;
tResult |= *pBuf --;
}

return  tResult;
}

// Read a big-endian TYPE from address
template
F3D_INLINE T GetBigEndian(const BYTE*  pBuf)
{
T tResult = 0;
for (int  I = 0; I < sizeof(T); ++ I)
{
tResult <<= 8;
tResult |= *pBuf ++;
}

return  tResult;
}

// Set a little-endian TYPE on a address
template
F3D_INLINE void SetLittleEndian(BYTE*  pBuf, T  t)
{
for (int  I = 0; I < sizeof(T); ++ I)
{
*pBuf ++ = BYTE(t & 0xFF);
t >>= 8;
}
}

// Set a big-endian T on a address
template
F3D_INLINE void SetBigEndian(BYTE*  pBuf, T  t)
{
pBuf += sizeof(T) - 1;
for (int  I = 0; I < sizeof(T); ++ I)
{
*pBuf -- = BYTE(t & 0xFF);
t >>= 8;
}
}

从上文可以看出,byte order挺简单的,一般应用中可能也用不上,但若您对写跨平台
的程序有兴趣,则一定要了解的比较清楚才行。以上代码都是从实际使用的源码中取下
来的。

附:常见Processor, OS的byte ordering情况

Processor OS Order
x86 (Intel, AMD, … ) All little-endian
DEC Alpha All little-endian
HP-PA NT little-endian
HP-PA UNIX big-endian
SUN SPARC All? big-endian
MIPS NT little-endian
MIPS UNIX big-endian
PowerPC NT little-endian
PowerPC non-NT big-endian
RS/6000 UNIX big-endian
Motorola m68k All big-endian

树的基本知识

1.树的分类:     ●一般树

C预编译 -编译-执行

C 语言编译原理简介 刚开始接触编程的时候,只知道照书敲敲代码,一直都不知道在windows 平台下的程 序代码经过鼠标那样点击几下,之后程序的结果就会在那个黑色的屏幕上,这期间到底发生 了些什...

ARM体系下浮点数Middle-Endian问题的处理

 随着嵌入式微处理器芯片性能的日益提高,嵌入式设备也得到了广泛的应用。随着应用的扩展,嵌入式软件开发也呈现出功能多样化、平台多样化、体系结构多样化的特点。       由于可移植性好,相当一部分嵌入式...

<转>趣谈unicode,ansi,utf-8,unicode big endian这些编码有什么区别

偶然看到,挺有意思,转发扩散~ 原文地址:http://blog.csdn.net/fanwenbo/article/details/2298800 从头讲讲编码的故事。那么就让我们找个草...

符号编码-ASCII、Unicode、Unicode big endian、UTF-8之间的关系(转)

1. ASCII 码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位( bit )有 0 和 1 两种状态,因此八个二进制位就可以组合出 256 种状态,这...
  • Yelbosh
  • Yelbosh
  • 2012年04月21日 12:38
  • 644

大端字节序和小端字节序问题(big-endian & little-endian)

转载来源:http://hi.baidu.com/michael1517/blog/item/12ff4dd3a5478d2e960a1631.html          谈到字节序的问题,必然牵...
  • mjsornp
  • mjsornp
  • 2011年08月12日 09:17
  • 2239

ORACLE的redo文件在不同机器上存储是否使用big-endian还是little-endian的问题

在解析ORACLE的dbf文件的时候,发现在不同的机器台上,存储使用的字节序并不一样. 今天看PostgreSQL 9.6.1更新版本发布说明的时候,看到这块有相关的描述: pg_up...

big-endian和little-endian问题

1.BIG-ENDIAN、LITTLE-ENDIAN跟多字节类型的数据有关的比如int,short,long型,而对单字节数据byte却没有影响。BIG-ENDIAN就是低位字节排放在内存的低端,高位...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[转]关于Endian的问题
举报原因:
原因补充:

(最多只允许输入30个字)