当前的存储器,多以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属于哪种字节存储顺序。代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#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;          //将i的地址传给数组指针p,实际上p指向的地址是i在内存中存储的第一个字节,大端就是0x12,小端就是0x78

    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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

#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;     //看num1的16进制表示,下同

    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*)&num;

    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位吗。

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

1

2

3

4

5

UINT EndianConvertLToB(UINT InputNum) {

    UCHAR *p = (UCHAR*)&InputNum;

    return(((UINT)*p<<24)+((UINT)*(p+1)<<16)+

               ((UINT)*(p+2)<<8)+(UINT)*(p+3));

}

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

1

2

3

4

5

UINT EndianConvertBToL(UINT InputNum) {

    UCHAR *p = (UCHAR*)&InputNum;

    return(((UINT)*p)+((UINT)*(p+1)<<8)+

               ((UINT)*(p+2)<<16)+(UINT)*(p+3)<<24);

}

分类: C/C++

标签: 大端和小端, 转换, 判断

大端和小端的判断及转换相关推荐

  1. 大端和小端的判断(计算机操作系统篇)

    1.什么是大端和小端 大端是指低字节存储在高地址:小端存储是指低字节存储在低地址.下图为小端存储方式 2.如何判断大端和小端 我们可以根据联合体来判断该系统是大端还是小端. 因为联合体变量总是从地址存 ...

  2. 题目:如何判断一个机器是大端还是小端

    如何判断一个机器是大端还是小端 关于大端小端的概念, 小端:数据的高位字节存放在高地址内,数据的低位字节存放在低地址内. 大端:数据的高位字节存放在低地址内,数据的低位字节存放在高地址内. 典型的体系 ...

  3. 大端和小端的含义及判断代码

    1.概述 在计算机系统中,数据都是以字节进行存储的,每个地址单元对应一个字节,每个字节都是8位(bit).但是C++除了char和bool之外,还有其它多字节类型.怎样存储多字节的数据就分为了大端和小 ...

  4. 网络通信之 字节序转换原理与网络字节序、大端和小端模式

    一.在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换. 原因如下:网络协议规定接收到得第一个字节是高字节, ...

  5. 大端和小端的区别,以及如何判断一台机器是大端还是小端?

    如何判断一台机器是大端还是小端 判断方式如下 判断方式如下 采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字 ...

  6. 大端字节序与小端字节序的转换

    逐步加深对字节操作的理解,记录一下大端字节序与小端字节序的转换,开发环境是vs2010,项目类型是控制台输出程序,下面是代码实现: // ByteOrder_demo.cpp : 定义控制台应用程序的 ...

  7. 网络通信时字节序转换原理与网络字节序、大端和小端模式 .

    引言:在进行网络通信时是否需要进行字节序转换? 相同字节序的平台在进行网络通信时可以不进行字节序转换,但是跨平台进行网络数据通信时必须进行字节序转换.原因如下:网络协议规定接收到得第一个字节是高字节, ...

  8. 判断 机器是大端还是小端(两种方法)

    什么是大端序,小端序?? 其实就是字节的存储顺序,如果数据都是单字节的,那怎么存储无所谓了,但是对于多字节数据,比如int,double等,就要考虑存储的顺序了. 举个例子: 一个32位 int 型变 ...

  9. 大端与小端以及如何判断大小端

    大端:将表示一个对象的字节在内存中按照从最高有效字节到最低有效字节的顺序存储,即最高有效字节在内存地址最前面的方式,称为大端法 小端:将表示一个对象的字节在内存中按照从最低有效字节到最高有效字节的顺序 ...

最新文章

  1. RACER: Rapid and accurate correction of errors in reads 快速、准确地修正读数中的错误
  2. php数组,常量,遍历等
  3. golang sleep函数 休眠延时
  4. 20145228《Java程序设计》课程总结
  5. 【转】RMAN 高级恢复
  6. SerialPort comstat is being used without defining
  7. 数论概论(Joseph H.Silverman) 习题 39.1 $\sqrt{3}$和$\sqrt{5}$的连分数展开中的重复现象...
  8. 你不知道的数学趣闻(一)
  9. 别人用钱,而我用python爬虫爬取了一年的4K高清壁纸
  10. 优化 Perl 榨取代码的最大性能
  11. Docker入门之四搭建私有仓库
  12. AngularJS+ASP.NET MVC+SignalR实现消息推送
  13. [ CSS ] animation 快速参考
  14. Windows mobile美化之-短信界面美化修改~
  15. Declustered RAID
  16. python用空格隔开每一个字符_Python(字符串操作实例1)一个字符串用空格隔开
  17. MathType中/英文版下载地址汇总(适用于Mathtype6.9)
  18. HTML5开发系列(4) 之 样式表的三种类型
  19. ES6基本的语法(十六) lterator
  20. php设备在线报修,php企业设备报修系统

热门文章

  1. 无法识别的属性“targetFramework”。请注意属性名称区分大写和小写。错误解决的方法...
  2. js日期的初始化的格式
  3. 三种Ext提交数据的方法(转)
  4. 自动生成存储过程的脚本
  5. Daily Report 2012.11.9 刘宇翔
  6. 什么是类、对象、方法、属性、类的成员
  7. 7-55 空心字母金字塔 (10 分)
  8. 基于oracle设计与实现,基于Oracle的高校研究生招生系统设计与实现.doc
  9. 恒为linux笔试题,硬件工程师面试试题及答案(转)
  10. mysql 技能进阶_mysql的高级进阶(一)