字节存储排序:大端(big endian)和小端(little)的判别及转换

原创 2015年07月09日 18:46:15

当前的存储器,多以byte为访问的最小单元,当一个逻辑上的地址必须分割为物理上的若干单元时就存在了先放谁后放谁的问题,于是端(endian)的问题应运而生了,对于不同的存储方法,就有大端(big-endian)和小端(little- endian)两个描述。

字节排序按分为大端和小端,概念如下

大端(big endian):低地址存放高有效字节

小端(little endian):低字节存放地有效字节

现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian,ARM则同时支持 big和little,网络编程中,TCP/IP统一采用大端方式传送数据,所以有时我们也会把大端方式称之为网络字节序

特别需要注意的是,C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而 JAVA编写的程序则唯一采用big endian方式来存储数据。这里我就只讨论C/C++语言的情况。

1.大端和小端的方式及判断

举个例子说明,我的机子是32位windows的系统,处理器是AMD的。对于一个int型数0x12345678,为方便说明,这里采用16进制表示。这个数在不同字节顺序存储的CPU中储存顺序如下:

0x12345678   16进制,两个数就是一字节

高有效字节——>低有效字节: 12 34 56 78

          低地址位     高低址位

大端:  12  34        56   78

小端: 78  56        34   12

下面验证下本机CPU属于哪种字节存储顺序。代码如下:

#include <iostream> 
 
using namespace std;
 
typedef unsigned int UINT;
typedef unsigned char UCHAR;
 
int main()
{
    UINT i=0x12345678;
    cout<<hex<<i<<endl;
    UCHAR *p = (UCHAR*)&i;          <span style="color:#33cc00;">//将i的地址传给数组指针p,实际上p指向的地址是i在内存中存储的第一个字节,大端就是0x12,小端就是0x78</span>
    if((*p==0x78)&(*(p+1)==0x56))        
        cout<<"小端"<<endl;
    else if((*p==0x12)&(*(p+1)==0x34))
        cout<<"大端"<<endl;
    else
        cout<<"这是神马字节顺序呢?";
    return 0;
}


调试显示时小端,我用的机子字节存储为小端方式。

2.大端和小端的字节转换

当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序(即大端方式)后再进行传输。此外用C/C++在小端方式的机器上编写的程序与java程序互通时也要进行大端和小端的转换。

这里所谓转换就是改变字节的排序,使交互时数据保持一致。举一个例子,还是16进制表示的数0x12345678,在小端机器上排序为0x78563412,当内存中这样的数传输时,在大端方式下就是0x78563412这个值,与原值不同,要想与原值相同,在传输前,在大端方式下就该是0x12345678,这时原数在内存中为0x12345678,即将原数据0x12345678在内存存储序列为0x12345678,也就是要转换成大端方式。

要传输值:12 34 56 78

不转换时,小端:78 56 34 12

转换为大端:12 34 56 78

根据上面的大端和小端字节排序,可以方便的用移位运算完成转换功能。从小端转到大端代码如下:

#include <iostream>
 
using namespace std;
 
typedef unsigned int UINT;
typedef unsigned char UCHAR;
 
int main()
{
    UINT i=0x12345678;
    cout<<hex<<i<<endl;
    UCHAR *p = (UCHAR*)&i; 
    UINT num,num1,num2,num3,num4;
    num1=(UINT)(*p)<<24;
    num2=((UINT)*(p+1))<<16;
    num3=((UINT)*(p+2))<<8;
    num4=((UINT)*(p+3));
    num=num1+num2+num3+num4;
 
    cout<<"num1:"<<hex<<num1<<endl;     <span style="color:#33ff33;">//看num1的16进制表示,下同</span>
    cout<<"num2:"<<hex<<num2<<endl;
    cout<<"num3:"<<hex<<num3<<endl;
    cout<<"num4:"<<hex<<num4<<endl;
    cout<<"num:"<<hex<<num<<endl;
 
    unsigned char *q = (unsigned char*)#
    if((*q==0x78)&(*(q+1)==0x56))          
        cout<<"小端"<<endl;
    else if((*q==0x12)&(*(q+1)==0x34))
        cout<<"大端"<<endl;
    else
        cout<<"这是神马字节顺序呢?";
    return 0;
}


至于说(UINT)(*p)为什么要移24位,其实是很好理解的,将0x00000012变成0x12000000,不就是向左移24位吗。

当然,向上面这样写时为了方便理解,可以更简单的写一个函数用于完成上面的转换功能,函数如下:

UINT EndianConvertLToB(UINT InputNum) {
    UCHAR *p = (UCHAR*)&InputNum;
    return(((UINT)*p<<24)+((UINT)*(p+1)<<16)+
               ((UINT)*(p+2)<<8)+(UINT)*(p+3));
}


同样的原理适用于大端转小端,但是大端转小端时移位有差别,函数如下:

UINT EndianConvertBToL(UINT InputNum) {
    UCHAR *p = (UCHAR*)&InputNum;
    return(((UINT)*p)+((UINT)*(p+1)<<8)+
               ((UINT)*(p+2)<<16)+(UINT)*(p+3)<<24);
}


字节序——大端(Big Endian)和小端(Little Endian)

每次碰到这个问题都需要现查资料,脑子不够用啊,索性就把它的来龙去脉写下来,加深一下印象。 1. 字节序问题的存在原因 自计算机采用byte作为存储单位起,字节序就是一个有争议的话题。这是因为我们通...
  • scaleqiao
  • scaleqiao
  • 2015年01月17日 17:27
  • 941

大端BigEndian、小端LittleEndian与字符集编码

BigEndian(大端):低字节在高内存地址 LittleEndian(小端):低字节在低内存地址也就是看低字节在高内存地址还是低内存地址,也就是看低字节在前还是高字节在前,低字节在前自然是小端,...
  • joenqc
  • joenqc
  • 2017年05月04日 18:34
  • 699

Little Endian, Big Endian, 网络字节序

字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。 Little Endian还是Big Endian与操作系统和芯片类型都有关系。 Motorola的PowerPC系列C...
  • cai0612123
  • cai0612123
  • 2016年08月15日 16:00
  • 404

ARM Endian(字节序)初探

Endian这个词在有道词典中这样描述:名词,字节存储次序,元组排列顺序,字节序 这个单词的出处是讽刺小说《格利佛游记》,百度百科上的描述是: 在小人国里的小人因为非常小(身高6英寸)所以总是碰到一些...
  • lincyang
  • lincyang
  • 2013年12月11日 17:21
  • 9412

大端小端以及51单片机,CORTEX M 32位单片机中的归属

1 定义:         大端模式,是指数据的高位保存在内存的低地址中,而数据的低位保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放...
  • wzk456
  • wzk456
  • 2014年11月11日 22:58
  • 1577

字节顺序的详细解释--关于Big endian和 Little endian

一、基本概念位的概念:在计算机中,一个0或1称为一位(bit)。字节:连续的八位称为一个字节(Byte),字节是计算机中可单独处理的最小单位。即以字节为基本单位来解释信息,规定1个字节是8个二进制位。...
  • wave_1102
  • wave_1102
  • 2007年10月29日 09:59
  • 2101

详解Big-Endian和Little-Endian,大端模式和小端模式

详解大端模式和小端模式 嵌入式开发交流群280352802,欢迎加入! 一、大端模式和小端模式的起源         关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的...
  • zhangpinghao
  • zhangpinghao
  • 2013年11月01日 22:00
  • 2161

关于字节序Big Endian和Little Endian

关于字节序 字节序指的是一个大于2个字节的类型的数据例如int 、long等在内存中的字节顺序。 字节序分为:网络字节序 (Big Endian) 比如 0x11223344 ,占四个字节...
  • yue7603835
  • yue7603835
  • 2017年05月17日 22:21
  • 658

字节序:Big Endian 和 Little Endian

一、字节序字节序,也就是字节的顺序,指的是多字节的数据在内存中的存放顺序。在几乎所有的机器上,多字节对象都被存储为连续的字节序列。例如:如果C/C++中的一个int型变量 a 的起始地址是&a = ...
  • lisong694767315
  • lisong694767315
  • 2015年05月01日 21:11
  • 2011

CPU存储方式—Big Endian、Little Endian

嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解,采用Little-endian模式的CPU对操作数的存放方式是低字节到高字节,而Big-endian模式CPU对操作...
  • jpbj_zb
  • jpbj_zb
  • 2016年05月09日 13:57
  • 662
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:字节存储排序:大端(big endian)和小端(little)的判别及转换
举报原因:
原因补充:

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