大端与小端

简单测试大端机器与小端机器

用例:

#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位读写操作所得到的结果与小端模式的处理器不同。单纯从软件的角度理解上远远不能真正理解大小端模式的区别。事实上,真正的理解大小端模式的区别,必须要从系统的角度,从指令集,寄存器和数据总线上深入理解,大小端模式的区别。


转载自:
详解大端与小端

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值