简单测试大端机器与小端机器
用例:
#include <iostream>
bool isBigEnd()
{
int a = 0x1234;
char b = *(char *)&a;
if (b == 0x12)
return true;
else
return false;
}
bool isBigEnding()
{
union {
int a;
char b;
}obj;
obj.a = 0x1234;
if (obj.b == 0x12)
return true;
else
return false;
}
int main()
{
std::cout<<isBigEnd()<<std::endl;
std::cout<<isBigEnding()<<std::endl;
return 0;
}
分析:
union 是利用了它的性质:
所有成员从低地址开始存放
小端:
0x0000 01
0x0001 00
0x0002 00
0x0003 00
大端:
0x0000 00
0x0001 00
0x0002 00
0x0003 01
详解大端与小端:
大端小端优劣:
大端与小端没有优劣之分,表示不同而已
小端在计算机内进行数值转换时候不需要移位。
而大端的符号位判定总是访问第一个字节就可以了。
数组在大端和小端机下的存储:
unsigned int value = 0x12345678;
unsigned char buf[4];
小端:
buf[0] = 0x78 低位
buf[1] = 0x56
buf[2] = 0x34
buf[3] = 0x12 高位
大端:
buf[0] = 0x12 高位
buf[1] = 0x34
buf[2] = 0x56
buf[3] = 0x78 低位
常见的字节序:
一般的操作系统为小端, 而通信协议通常为大端。
常见CPU的字节序
Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM既可以工作在大端模式,也可以工作在小端模式。
常见文件的字节序
Adobe PS – Big Endian
BMP – Little Endian
DXF(AutoCAD) – Variable
GIF – Little Endian
JPEG – Big Endian
MacPaint – Big Endian
RTF – Little Endian
另外,Java和所有的网络通讯协议都是使用Big-Endian的编码。
如何进行大端与小端的转换呢?
16位字数据
#define BigtoLittle16(A)
(( ((uint16)(A) & 0xff00) >> 8) | \
(( (uint16)(A) & 0x00ff) << 8))
32位双字数据
#define BigtoLittle32(A)
((( (uint32)(A) & 0xff000000) >> 24) | \
(( (uint32)(A) & 0x00ff0000) >> 8) | \
(( (uint32)(A) & 0x0000ff00) << 8) | \
(( (uint32)(A) & 0x000000ff) << 24) )
从软件的角度上,不同端模式的处理器进行数据传递时必须要考虑端模式的不同。如进行网络数据传递时,必须要考虑端模式的转换。在Socket接口编程中,以下几个函数用于大小端字节序的转换。
#include <arpa/inet.h>
#define ntohs(n)
//16位数据类型网络字节顺序到主机字节顺序的转换
#define htons(n)
//16位数据类型主机字节顺序到网络字节顺序的转换
#define ntohl(n)
//32位数据类型网络字节顺序到主机字节顺序的转换
#define htonl(n)
//32位数据类型主机字节顺序到网络字节顺序的转换
其中互联网使用的网络字节顺序采用大端模式进行编址,而主机字节顺序根据处理器的不同而不同,如PowerPC处理器使用大端模式,而Pentuim处理器使用小端模式。
大端模式处理器的字节序到网络字节序不需要转换,此时ntohs(n)=n,ntohl = n;而小端模式处理器的字节序到网络字节必须要进行转换,此时ntohs(n) = __swab16(n),ntohl = __swab32(n)。__swab16与__swab32函数定义如下所示。
#define ___swab16(x)
{
__u16 __x = (x);
((__u16)(
(((__u16)(__x) & (__u16)0x00ffU) << 8) |
(((__u16)(__x) & (__u16)0xff00U) >> 8) ));
}
#define ___swab32(x)
{
__u32 __x = (x);
((__u32)(
(((__u32)(__x) & (__u32)0x000000ffUL) << 24) |
(((__u32)(__x) & (__u32)0x0000ff00UL) << 8) |
(((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) |
(((__u32)(__x) & (__u32)0xff000000UL) >> 24) ));
}
PowerPC处理器提供了lwbrx,lhbrx,stwbrx,sthbrx四条指令用于处理字节序的转换以优化__swab16和__swap32这类函数。此外PowerPC处理器中的rlwimi指令也可以用来实现__swab16和__swap32这类函数。
在对普通文件进行处理也需要考虑端模式问题。在大端模式的处理器下对文件的32,16位读写操作所得到的结果与小端模式的处理器不同。单纯从软件的角度理解上远远不能真正理解大小端模式的区别。事实上,真正的理解大小端模式的区别,必须要从系统的角度,从指令集,寄存器和数据总线上深入理解,大小端模式的区别。
转载自:
详解大端与小端