精华内容
下载资源
问答
  • 大端模式

    2013-04-14 11:16:23
    计算机中的大端模式(Endian)的这个词出自JonathanSwift书写的《格列佛游记》。这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为BigEndian,从尖头开始将鸡蛋敲开的人被归为...
    计算机中的大端 
    
    端模式(Endian)的这个词出自JonathanSwift书写的《格列佛游记》。这本书根据将鸡蛋敲开的方法不同将所有的人分为两类,从圆头开始将鸡蛋敲开的人被归为BigEndian,从尖头开始将鸡蛋敲开的人被归为LittileEndian。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头( Little-Endian)敲开。在计算机业BigEndian和LittleEndian也几乎引起一场战争。在计算机业界,Endian表示数据在 存储器中的存放顺序。下文举例说明在计算机中大小端模式的区别。
    如果将一个32位的整数0x12345678存放到一个 整型变量(int)中,这个整型变量采用大端或者小端模式在内存中的存储由下表所示。为简单起见,本书使用OP0表示一个32位数据的最高字节MSB(Most Significant Byte),使用OP3表示一个32位数据最低字节LSB(Least Significant Byte)。
    ;地址偏移
    ;大端模式
    ;小端模式
    0x00
    12(OP0)
    78(OP3)
    0x01
    34(OP1)
    56(OP2)
    0x02
    56(OP2)
    34(OP1)
    0x03
    78(OP3)
    12(OP0)
    如果将一个16位的整数0x1234存放到一个短 整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示。
    ;地址偏移
    ;大端模式
    ;小端模式
    0x00
    12(OP0)
    34(OP1)
    0x01
    34(OP1)
    12(OP0)
    由上表所知,采用大小模式对数据进行存放的主要区别在于在存放的 字节顺序,大端方式将高位存放在低地址,小端方式将高位存放在高地址。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。到目前为止,采用大端或者小端进行数据存放,其孰优孰劣也没有定论。
    有的处理器系统采用了小端方式进行数据存放,如Intel的奔腾。有的处理器系统采用了大端方式进行数据存放,如IBM半导体和Freescale的PowerPC处理器。不仅对于处理器,一些外设的设计中也存在着使用大端或者小端进行数据存放的选择。
    因此在一个处理器系统中,有可能存在大端和小端模式同时存在的现象。这一现象为系统的软硬件设计带来了不小的麻烦,这要求系统设计工程师,必须深入理解大端和小端模式的差别。大端与小端模式的差别体现在一个处理器的寄存器,指令集,系统总线等各个层次中。
    展开全文
  • 大端模式和小端模式

    万次阅读 多人点赞 2018-08-28 17:09:25
    大端模式(Big-endian):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端,即正序排列,高尾端; 小端模式(Little-endian):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端,即逆序...

     

    一.概念

    大端模式(Big-endian):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端,即正序排列,高尾端;

    小端模式(Little-endian):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端,即逆序排列,低尾端;

    例(无论是小端模式还是大端模式。每个字节内部都是按顺序排列):

    1)大端模式:

    低地址 -----------------> 高地址

    0x0A  |  0x0B  |  0x0C  |  0x0D

    2)小端模式:

    低地址 ------------------> 高地址

    0x0D  |  0x0C  |  0x0B  |  0x0A

    3)下面是两个具体例子:

    16bit宽的数0x1234在两种模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

    内存地址小端模式存放内容大端模式存放内容
    0x40000x340x12
    0x40010x120x34

    32bit宽的数0x12345678在两种模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

    内存地址小端模式存放内容大端模式存放内容
    0x40000x780x12
    0x40010x560x34
    0x40020x340x56
    0x40030x120x78

    4)大端小端没有谁优谁劣,各自优势便是对方劣势:

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

    二、数组在大端小端模式下的存储:

    以unsigned int num = 0x12345678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示num:
    Big-Endian: 低地址存放高位,如下:

    低地址

    ---------------

    buf[0] (0x12) -- 高位 

    buf[1] (0x34)

    buf[2] (0x56)

    buf[3] (0x78) -- 低位

    ---------------
    高地址
     
    Little-Endian: 低地址存放低位,如下:

    低地址

    ---------------

    buf[0] (0x78) -- 低位

    buf[1] (0x56)

    buf[2] (0x34)

    buf[3] (0x12) -- 高位

    --------------

    高地址

    三、为什么会有大小端模式之分呢?

           这是因为在计算机中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8 bit。但是在C 语言中除了 8 bit 的char之外,还有 16 bit 的 short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着如果将多个字节安排的问题。大端存储模式和小端存储模式也就应运而生。例如一个16bit的short型 x ,在内存中的地址为 0x0010,x 的值为0x1122,那么0x11位高字节,0x22位低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

    四、如何判断机器的字节序 (重点)

    一般都是通过 union 来测试的,下面这段代码可以用来测试一下你的编译器是大端模式还是小端模式:

    #include <stdio.h>
    
    int main (void)
    {
    union{
    short i;
    char a[2];
    }u;//联合体u
    
    u.a[0] = 0x11;
    u.a[1] = 0x22;
    
    printf ("0x%x\n", u.i); //0x2211 为小端 0x1122 为大端
    return 0;
    }
    
    输出结果:
    0x2211

          union 型数据所占的空间等于其最大的成员所占的空间。对 union 型的成员的存取都是相对于该联合体基地址的偏移量为 0 处开始,也就是联合体的访问不论对哪个变量的存取都是从 union 的首地址位置开始

         联合是一个在同一个存储空间里存储不同类型数据的数据类型。这些存储区的地址都是一样的,联合里不同存储区的内存是重叠的,修改了任何一个其他的会受影响。那么通过强制类型转换,判断其实存储位置,也可以测试大小端了:

    #include <stdio.h>
    
    int main (void)
    {
    short i = 0x1122;
    char *a = (char*)(&i);
    
    printf ("0x%x\n", *(a + 0)); //大端为 0x11 小端为 0x22
    printf ("0x%x\n", *(a + 1));
    return 0;
    }
    
    输出结果:
    0x22
    0x11

    五、常见的字节序

    一般操作系统都是小端,而通讯协议是大端的。

    1)常见CPU的字节序

    Big Endian : PowerPC、IBM、Sun
    Little Endian : x86、DEC
    ARM既可以工作在大端模式,也可以工作在小端模式。

    2)常见文件的字节序

    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的编码。

    六、如何进行大小端转换(重点)

    第一种方法:位操作

    #include<stdio.h>
    typedef unsigned int uint_32 ;
    typedef unsigned short uint_16 ;
    
    //16位
    #define BSWAP_16(x) \
    (uint_16)((((uint_16)(x) & 0x00ff) << 8) | \ (((uint_16)(x) & 0xff00) >> 8) \)
    
    //32位
    #define BSWAP_32(x) \
    (uint_32)((((uint_32)(x) & 0xff000000) >> 24) | \ (((uint_32)(x) & 0x00ff0000) >> 8) | \
    (((uint_32)(x) & 0x0000ff00) << 8) | \ (((uint_32)(x) & 0x000000ff) << 24) \)
    
    //无符号整型16位
    uint_16 bswap_16(uint_16 x)
    {
      return (((uint_16)(x) & 0x00ff) << 8) | \ (((uint_16)(x) & 0xff00) >> 8) ;
    }
    
    //无符号整型32位
    uint_32 bswap_32(uint_32 x)
    {
      return (((uint_32)(x) & 0xff000000) >> 24) | \ (((uint_32)(x) & 0x00ff0000) >> 8) | \
      (((uint_32)(x) & 0x0000ff00) << 8) | \ (((uint_32)(x) & 0x000000ff) << 24) ;
    }
    
    int main(int argc,char *argv[])
    {
     printf("------------带参宏-------------\n");
     printf("%#x\n",BSWAP_16(0x1234)) ;
     printf("%#x\n",BSWAP_32(0x12345678));
     printf("------------函数调用-----------\n");
     printf("%#x\n",bswap_16(0x1234)) ;
     printf("%#x\n",bswap_32(0x12345678));
     return 0 ;
    }
    
    输出结果:
    ------------带参宏-------------
    0x3412
    0x78563412
    ------------函数调用-----------
    0x3412
    0x78563412

    这里有个思考?上面的哪个是转换为大端,哪个是转为小端了呢?

    举个例子,比如数字 0x12 34 56 78在内存中的表示形式为:

    1)大端模式:

    低地址 -----------------> 高地址

    0x12  |  0x34  |  0x56  |  0x78

    2)小端模式:

    低地址 ------------------> 高地址

    0x78  |  0x56  |  0x34  |  0x12

    则:

    转换为大端:

    pPack[2] = (u8)((len >> 8) & 0xFF);
    pPack[3] = (u8)(len & 0xFF);

    转为为小端:

    pPack[2] = (u8)(len & 0xFF);

    pPack[3] =  (u8)((len >> 8) & 0xFF);

     

    第二种方法:从软件的角度理解端模式,使用 htonl, htons, ntohl, ntohs 等函数

    参看:百度百科--htonl ()函数

    参看:百度百科--htons ()函数

    查看:man htonl

    NAME
    htonl, htons, ntohl, ntohs - convert values between host and network byte order
    SYNOPSIS
    #include <arpa/inet.h>
    
    uint32_t htonl(uint32_t hostlong);
    uint16_t htons(uint16_t hostshort);
    uint32_t ntohl(uint32_t netlong);
    uint16_t ntohs(uint16_t netshort);
    
    DESCRIPTION
    The htonl() function converts the unsigned integer hostlong from host byte order to network byte order.
    
    The htons() function converts the unsigned short integer hostshort from host byte order to network byte order.
    
    The ntohl() function converts the unsigned integer netlong from network byte order to host byte order.
    
    The ntohs() function converts the unsigned short integer netshort from network byte order to host byte order.
    
    On the i386 the host byte order is Least Significant Byte first, whereas the network byte order, as used on the Internet, is Most
    
    Significant Byte first.

    解释

    htonl()     //32位无符号整型的主机字节顺序到网络字节顺序的转换(小端->>大端)
    htons() 
        //16位无符号短整型的主机字节顺序到网络字节顺序的转换  (小端->>大端)
    ntohl()     //32位无符号整型的网络字节顺序到主机字节顺序的转换  (大端->>小端)
    ntohs()     //16位无符号短整型的网络字节顺序到主机字节顺序的转换  (大端->>小端)

    注,主机字节顺序,X86一般多为小端(little-endian),网络字节顺序,即大端(big-endian);

    举两个小例子:

    //示例一
    
    #include <stdio.h>
    #icnlude <arpa/inet.h>
    
    int main (void){
      union{
        short i;
        char a[2];
      }u;
       u.a[0] = 0x11;
    
       u.a[1] = 0x22;
    
       printf ("0x%x\n", u.i); //0x2211 为小端 0x1122 为大端
       printf ("0x%.x\n", htons (u.i)); //大小端转换
       return 0;
    }
    
    输出结果:
    0x2211
    0x1122
    //示例二
    
    #include <stdio.h>
    #include <arpa/inet.h>
    
    struct ST{
    short val1;
    short val2;
    };
    
    union U{
    int val;
    struct ST st;
    };
    
    int main(void)
    {
    int a = 0;
    union U u1, u2;
    a = 0x12345678;
    u1.val = a;
    
    printf("u1.val is 0x%x\n", u1.val);
    printf("val1 is 0x%x\n", u1.st.val1);
    printf("val2 is 0x%x\n", u1.st.val2);
    printf("after first convert is: 0x%x\n", htonl(u1.val));
    
    u2.st.val2 = htons(u1.st.val1);
    u2.st.val1 = htons(u1.st.val2);
    printf("after second convert is: 0x%x\n", u2.val);
    return 0;
    }
    
    输出结果:
    u1.val is 0x12345678
    val1 is 0x5678
    val2 is 0x1234
    after first convert is: 0x78563412
    after second convert is: 0x78563412
    
    

            在对普通文件进行处理也需要考虑端模式问题。在大端模式的处理器下对文件的32,16位读写操作所得到的结果与小端模式的处理器不同。单纯从软件的角度理解上远远不能真正理解大小端模式的区别。事实上,真正的理解大小端模式的区别,必须要从系统的角度,从指令集,寄存器和数据总线上深入理解,大小端模式的区别。 

    七.验证当前机器系统的存储方式是大端还是小端

    #include <stdio.h>
    #include <conio.h>
    union Test {
    	short num;
    	char c[sizeof(short)];
    };
    int main()
    {
    	union Test t;
    	t.num = 0x0102;
    	if (t.c[0] == 1 && t.c[1] == 2)
    		printf("大端!\n");
    	else if (t.c[0] == 2 && t.c[1] == 1)
    		printf("小端!\n");
    	else
    		printf("未知!\n");
    	getchar();
        //system("PAUSE"); C函数,C++中需包含头文件#include<stdlib.h>
    	return 0;
    }

     

    展开全文
  • 详解大端模式和小端模式

    万次阅读 多人点赞 2011-11-16 20:21:29
    详解大端模式和小端模式 一、大端模式和小端模式的起源  关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因...

    详解大端模式和小端模式

    嵌入式开发交流群280352802,欢迎加入!

    一、大端模式和小端模式的起源

            关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。
     

    二、什么是大端和小端

    展开全文
  • 深刻理解大端模式与小端模式的概念,但我们如何判别当前系统为大端模式还是小端模式呢?
  • 大端模式 小端模式

    2020-11-27 23:29:30
    1、大端模式:高字节保存在内存的低地址 2、小端模式:高字节保存在内存的高地址 我比较喜欢这么记忆 小端模式:低地址在小端 大端模式:低地址在大端 例子: 举例: var = 0x11223344,对于这个变量的最高字节为0x...

    通过一句话记住大端序和小端序的区别

    在软件开发过程中,软件开发人员都知道大端序和小端序的概念,但是在真正使用的时候,傻傻分不清两种到底是怎么存储。

    首先还是先看下基本概念:

    1、大端模式:高字节保存在内存的低地址

    2、小端模式:高字节保存在内存的高地址

    我比较喜欢这么记忆
    小端模式:低字节在低地址
    大端模式:高字节在大地址

    例子:
    举例:

    var = 0x11223344,对于这个变量的最高字节为0x11,最低字节为0x44

    (1)大端模式存储(存储地址为16位)

    地址 数据

    0x0004(高地址) 0x44

    0x0003 0x33

    0x0002 0x22

    0x0001(低地址) 0x11

    (2)小端模式存储(存储地址为16位)

    地址 数据

    0x0004(高地址) 0x11

    0x0003 0x22

    0x0002 0x33

    0x0001(低地址) 0x44

    测试电脑cpu是大端还是小端

    
    	int nNum = 0x12345678;//78占一个字节 (一个字节等于8bit)
    	char chData = *(char*)(&nNum);//低地址
    
    	if (chData == 0x78)//低字节放在低位  ---》小端
    	{
    		cout << "small" << endl;
    	}
    	else
    	{
    		cout << "big" << endl;
    	}
    
    	system("PAUSE");
    

    我的电脑运行结果
    small

    和我在内存中看到的一致(低字节在低地址)
    在这里插入图片描述

    展开全文
  • 大端模式小端模式

    2017-09-08 14:38:12
    大端模式小端模式
  • 大端模式与小端模式

    2018-09-11 10:21:34
    大端模式 所谓的大端模式(Big-endian),是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位...
  •  在各种体系的计算机中通常采用的字节存储机制主要有两种: big-endian和little-endian,即大端模式和小端模式。  先回顾两个关键词,MSB和LSB:  MSB:Most Significant Bit ------- 最高有效位 LSB:Least ...
  • TPM大端模式

    2019-09-21 10:11:17
    1. Big-Endian(BE)大端模式 数据是按照,“高字节、低存储”,即高字节存储在低地址,符合人们直观感受 2. Little-Endian(LE)小端模式 数据是按照,“低字节,低存储”,即低字节存储在低地址,方便计算机做...
  • 大端模式和小端模式 背景 在内存中一个地址存储一个字节(Byte)的数据,即8位。 一个int型数据有32位,需要占用4Byte的空间,那么应该怎么存储int的数据呢?是高位先存储还是低位先存储?因此产生了两种不同的...
  • 小端模式 & 大端模式

    2021-01-17 21:25:55
    大端模式, 则与小端模式相反. inline bool IsLittleendian() { int i = 0x1; return *(char *)&i == 0x1; } int整型在内存中有4Bytes大小 int i = 0x1; 在内存中, 如果是大端模式,这内存的存储如下 |0x00|0x...
  • 大端模式 vs 小端模式

    2021-05-30 13:52:26
    大端模式 VS 小端模式一:大小端之分的由来二:内容代码解析:方法一:方法二: 一:大小端之分的由来 这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,370
精华内容 7,748
关键字:

大端模式