大端与小端

来源:互联网 发布:特蕾莎修女知乎 编辑:程序博客网 时间:2024/04/19 16:34

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

用例:

#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 010x0001 000x0002 000x0003 00大端:0x0000 000x0001 000x0002 000x0003 01

详解大端与小端:

大端小端优劣:

大端与小端没有优劣之分,表示不同而已
小端在计算机内进行数值转换时候不需要移位。
而大端的符号位判定总是访问第一个字节就可以了。

数组在大端和小端机下的存储:

unsigned int value = 0x12345678;unsigned char buf[4];小端:buf[0] = 0x78 低位buf[1] = 0x56buf[2] = 0x34buf[3] = 0x12 高位大端:buf[0] = 0x12 高位buf[1] = 0x34buf[2] = 0x56buf[3] = 0x78 低位

常见的字节序:

一般的操作系统为小端, 而通信协议通常为大端。

常见CPU的字节序

Big Endian : PowerPC、IBM、SunLittle Endian : x86、DECARM既可以工作在大端模式,也可以工作在小端模式。

常见文件的字节序

Adobe PS – Big EndianBMP – Little EndianDXF(AutoCAD) – VariableGIF – Little EndianJPEG – Big EndianMacPaint – Big EndianRTF – 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
原创粉丝点击