大小端

来源:互联网 发布:人工智能程序的维护 编辑:程序博客网 时间:2024/04/30 10:28

1.定义
大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;小端模式相反


2.为什么有大小端之分?
因为在计算机系统中,存储是以字节为单位的,每个地址单元都对应着一个字节,一个字节=8bit。在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,如何安排多个字节的存储,这就有了大端存储模式和小端存储模式


3.各自的优势:
小端模式:强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样。
大端模式:符号位的判定固定为第一个字节,容易判断正负。


4.常用的字节序
  一般操作系统都是小端,而通讯协议是大端的。
  4.1 常见CPU的字节序
    Big Endian : PowerPC、IBM、Sun
    Little Endian : x86、DEC
    ARM既可以工作在大端模式,也可以工作在小端模式。
 
  4.2 常见文件的字节序
    Adobe PS – Big Endian
    BMP – Little Endian
    DXF(AutoCAD) – Variable
    GIF – Little Endian
    JPEG – Big Endian
    MacPaint – Big Endian
    RTF – Little Endian
 
 4.3 另外,Java和所有的网络通讯协议都是使用Big-Endian的编码


5.C语言判断大小端模式
方法一:

bool IsBigEndian1(){short int a = 0x1122;//十六进制,一个数值占4位//通过将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)char b = *(char*)&a;if(b == 0x11)//低字节存的是数据的高字节数据{return true;//是大端模式}    else{return false;//是小端模式}}

方法二:

bool IsBigEndian2(){//原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间union temp{short int a;    char b;}temp;temp.a = 0x1234;if( temp.b == 0x12 )//低字节存的是数据的高字节数据{ return true;//是大端模式}else{return false;//是小端模式}}

6.转换字节序


c语言:
// "\"换行衔接的符号

#define BigtoLittle32(A)   ((( (uint32)(A) & 0xff000000) >> 24) | \                                         (( (uint32)(A) & 0x00ff0000) >> 8)   | \                                         (( (uint32)(A) & 0x0000ff00) << 8)   | \                                         (( (uint32)(A) & 0x000000ff) << 24))  

C++语言

#include <iostream>#include <cstdio>#include <iomanip>using namespace std;bool IsBigEndian1(){short int a = 0x1122;//十六进制,一个数值占4位//通过将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)char b = *(char*)&a;if(b == 0x11)//低字节存的是数据的高字节数据{return true;//是大端模式}    else{return false;//是小端模式}}bool IsBigEndian2(){//原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间union temp{short int a;    char b;}temp;temp.a = 0x1234;if( temp.b == 0x12 )//低字节存的是数据的高字节数据{ return true;//是大端模式}else{return false;//是小端模式}}template<typename T>inline T BigEndianToLittleEndian(const T & temp){static char move[8] = {7,5,3,1,1,3,5,7}; //打表法,提高效率 static char bitNum = 0;static T byte = 0, aByte = 0;T t = 0; char sizeType = sizeof(temp); //已知sizeType小于256 char pReal = sizeType >> 1; //已知pReal小于256 char *realMove = &move[3 - pReal + 1];  //已知realMove小于256 char moveByte = sizeType - 1; //空间换时间 if(sizeType > 1)for(int i = 0; moveByte > -1; ++i, --moveByte){//不能跟下一行合并,如果类型是long long,表达式类型自动提升只到int By gcc  bitNum = moveByte * 8; byte = 0xff;aByte = temp & (byte << bitNum);if( pReal > i )t |= aByte >> ((realMove[i]) * 8); elset |= aByte << ((realMove[i]) * 8);}elset = temp;return t;} template<typename T>inline T lToB(const T & temp){    char sizeType = sizeof(temp);char* begin = (char *)&temp;char* end = begin + sizeType - 1; while(begin < end){//小端低位数据存放在低地址序 //或者使用三次异或进行交换 swap(*(begin++), *(end--)); //#include<algorithm>}return temp;} template<typename T>inline T bToL(const T & temp){    char sizeType = sizeof(temp);char* begin = (char *)&temp;char* end = begin + sizeType - 1; while(begin > end){//大端低位数据存放在高地址序 //或者使用三次异或进行交换swap(*(begin++), *(end--)); //#include<algorithm>}return temp;} int main(){long long temp1 = 0x1234567890abcdef;int temp2       = 0x12345678;short int temp3 = 0x1234;char temp4      = 0x12;if(IsBigEndian1())cout << "大端" << endl;elsecout << "小端" << endl; cout << hex << BigEndianToLittleEndian(temp1); cout << hex << lToB(temp1) << endl;return 0;}



0 0