大端小端问题总结

大小端介绍问题总结

一、简介大小端定义

  • 大端模式
    所谓的大端模式,是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;
  • 小端模式
    所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

例子:在内存中双字0x12345678(DWORD)的存储方式
内存地址

         4000    4001    4002    4003 
LE       78        56        34        12 
BE       12        34        56        78

二、如何知道使用的CPU的大小端

对于一个数0x1122使用Little Endian方式时,低字节存储0x22,高字节存储0x11
而使用Big Endian方式时, 低字节存储0x11, 高字节存储0x22。
我们可以通过强制类型转换来判断CPU的大小端;

程序例子:

OTP_UINT8   test_data8 =0;
    OTP_UINT16  test_data16 =0;
    test_data16 = 0x1122;
    x0 = ((OTP_UINT8*)&test_data16)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data16)[1]; /*高地址单元*/
    test_data8=*( (unsigned char*) &test_data16 );
    if(test_data8 ==0x11)
    {
        printf("    CPU = big-endian 大端"SCRN_NEWLINE);
    }
    else
    {
        printf("    CPU = little-endian  小端"SCRN_NEWLINE);
    }

通过上例可以知道强制指针类型转换操作在大端系统和小端系统得出的内容是不一致的;
小端模式下:
OTP_UINT32型数据 = 0x12345678 , 指针类型强制转换后,OTP_UINT8为:0x78
OTP_UINT32型数据 = 0x12345678 , 指针类型强制转换后,OTP_UINT16为:0x5678
大端模式下:
OTP_UINT32型数据 = 0x12345678 , 指针类型强制转换后,OTP_UINT8为:0x12
OTP_UINT32型数据 = 0x12345678 , 指针类型强制转换后,OTP_UINT16为:0x1234

三、在大端、小端系统中对各类运算符操作的影响

  1. 通过编程测试,发现只有强制类型转换运算符在大小端系统中会得到不同的结果;
    数据的强制转换操作无影响;
    test_data8 =(OTP_UINT8)test_data32;
    test_data16 =(OTP_UINT16)test_data32;
    test_data32 =(OTP_UINT32)test_data8;
    指针的强制转换操作有影响
    test_data8=( (unsigned char) &test_data32 );
    test_data16=( (unsigned short) &test_data32 );

  2. 其它的位运算符如:>> 、<< 、|、;算术运算符等都没有影响;

  3. 使用移位操作的特殊应用:
    a_test_data8[0]=0x12;
    a_test_data8[1]=0x34;
    a_test_data8[2]=0x56;
    a_test_data8[3]=0x78;

    test_data32 =(OTP_UINT32)((a_test_data8[0]<<24)+ (a_test_data8[1]<<16)
    +(a_test_data8[2]<<8)+(a_test_data8[3]));
    test_data32的结果位0x12345678;
    这里在进行赋值操作前已经认为a_test_data8[0]中为高字节,a_test_data8[3]为低字节,上面的左移赋值操作在大端和小端的系统中得出的值是相同的;

    若在进行赋值操作前已经认为a_test_data8[0]中为低字节,a_test_data8[3]为高字节则操作为test_data32 =(OTP_UINT32)((a_test_data8[3]<<24)+ (a_test_data8[2]<<16)
    +(a_test_data8[1]<<8)+(a_test_data8[0]));

  4. 使用移位操作的特殊应用:
    test_data32 = 0x12345678;

    a_test_data8[0] =(test_data32>>24);
    a_test_data8[1] =(test_data32>>16);
    a_test_data8[2] =(test_data32>>8);
    a_test_data8[3] =(test_data32);
    上述操作完成后,a_test_data8[0]中为高字节=0x12,a_test_data8[3]=0x78 低字节;大端和小端的系统中是相同的;

四、字节序的转换方法

不同端模式的处理器进行数据传递时必须要考虑端模式的不同。如进行网络数据传递时,必须要考虑端模式的转换。在我们ROPT平台库里提供了转换函数:

    #define ntohs(n)     /*16位数据类型网络字节顺序到主机字节顺序的转换*/
    #define htons(n)     /*16位数据类型主机字节顺序到网络字节顺序的转换*/
    #define ntohl(n)     /*32位数据类型网络字节顺序到主机字节顺序的转换*/
    #define htonl(n)     /*32位数据类型主机字节顺序到网络字节顺序的转换*/

其中互联网使用的网络字节顺序采用大端模式进行编址,而主机字节顺序根据处理器的不同而不同,如PowerPC处理器使用大端模式,而Spear 310处理器使用小端模式。
大端模式处理器的字节序到网络字节序不需要转换,此时htons(n)=n,htonl = n;而小端模式处理器的字节序到网络字节必须要进行转换;

#define htonl(x)    ((((x) & 0x000000ff) << 24) | \
                        (((x) & 0x0000ff00) <<  8) | \
                        (((x) & 0x00ff0000) >>  8) | \
                        (((x) & 0xff000000) >> 24))

#define htons(x)    ((((x) & 0x00ff) << 8) | \
                        (((x) & 0xff00) >> 8))

所以在使用小端模式的CPU进行开发工作时,一旦涉及到数据的网络字节序传递,一定需要注意将整型、长整型进行网络字节序转换,否则会导致接收端数据错误;

五、在大端、小端系统中的比特序说明

一个采用大端模式的32位处理器,其寄存器的最高位msb(most significant bit)定义为0,最低位lsb(lease significant bit)定义为31;而小端模式的32位处理器,将其寄存器的最高位定义为31,低位地址定义为0。

例:按位域定义结构:

typedef union
{
    OTP_UINT32 Byte;
    struct
    {
        OTP_UINT32 a_bit0 :1;               
        OTP_UINT32 b_bit1 :1;
        OTP_UINT32 c_bit2_3:2;                  
        OTP_UINT32 d_bit4_13:10;                
        OTP_UINT32 e_bit14_21:8;                    
        OTP_UINT32 f_bit22_29:8;    
        OTP_UINT32 g_bit30:1;
        OTP_UINT32 h_bit31:1;   
    }bits;
}E1SlotCtrl;
E1SlotCtrl g_test_32;

这个共用体会占用4个字节。由于a,b,c,d,e,f,g,h的类型都是OTP_UINT32,所以他们都在以OTP_UINT32为单位的整数上分配bit。根据CPU大小端的不同,这些字节在这4个字节内是分配顺序也是不一样的。

程序中对结构体成员赋值:

    g_test_32.bits.a_bit0 =1;
    g_test_32.bits.b_bit1 =1;
    g_test_32.bits.c_bit2_3 =2;
    g_test_32.bits.d_bit4_13 =7;
    g_test_32.bits.e_bit14_21 =5;
    g_test_32.bits.f_bit22_29 =3;   
    g_test_32.bits.g_bit30 =0;      
    g_test_32.bits.h_bit31 =1;
打印的长整型数据如下:
在大端模式下g_test_32.Byte =0xe01c140d;
在小端模式下g_test_32.Byte =0x80c1407b;

具体的数据分配总结:
大端模式下g_test_32.Byte =0xe01c140d
Bit位定义 bit31(lsb) bit0(msb)
二进制码 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 1
结构成员 a b c d e f g h
结构成员值 1 1 2 7 5 3 0 1
小端模式下g_test_32.Byte =0x80c1407b;
Bit位定义 bit31(msb) bit0(lsb)
二进制码 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 1 0 1 1
结构成员 h g f e d c b a
结构成员值 1 0 3 5 7 2 1 1

所以直接使用位域的方式定义结构体是依赖于使用CPU的大小端模式的,当进行不同端系统移植的时候,必须重新定义这些结构体。

正确的位域定义方式:

typedef union
{
    OTP_UINT32 Byte;
    struct
    {
#ifdef  OTP_LITTLE_ENDIAN
        OTP_UINT32 a_bit0 :1;               
        OTP_UINT32 b_bit1 :1;
        OTP_UINT32 c_bit2_3:2;                  
        OTP_UINT32 d_bit4_13:10;                
        OTP_UINT32 e_bit14_21:8;                    
        OTP_UINT32 f_bit22_29:8;    
        OTP_UINT32 g_bit30:1;
        OTP_UINT32 h_bit31:1;                   
#else

        OTP_UINT32 h_bit31:1;                   
        OTP_UINT32 g_bit30:1;
        OTP_UINT32 f_bit22_29:8;
        OTP_UINT32 e_bit14_21:8;    
        OTP_UINT32 d_bit4_13:10;
        OTP_UINT32 c_bit2_3:2;  
        OTP_UINT32 b_bit1 :1;
        OTP_UINT32 a_bit0 :1;           

#endif
    }bits;
}E1SlotCtrl;

六、大端向小端系统移植代码时需要注意内容

  1. 有使用位域定义的结构,必须区分大小端进行定义;
  2. 需要进行网络字节序传递的整型、长整型数据必须进行网络字节序转换;
  3. 使用指针强制转换操作的需要根据端模式进行重新处理;
  4. 注意一些特殊的移位操作,见三.3、三.4;

七.附件:测试代码

typedef union
{
    OTP_UINT32 Byte;
    struct
    {
#if 1                           /*#ifdef    OTP_LITTLE_ENDIAN*/
        OTP_UINT32 a_bit0 :1;               
        OTP_UINT32 b_bit1 :1;
        OTP_UINT32 c_bit2_3:2;                  
        OTP_UINT32 d_bit4_13:10;                
        OTP_UINT32 e_bit14_21:8;                    
        OTP_UINT32 f_bit22_29:8;    
        OTP_UINT32 g_bit30:1;
        OTP_UINT32 h_bit31:1;                   
#else

        OTP_UINT32 h_bit31:1;                   
        OTP_UINT32 g_bit30:1;
        OTP_UINT32 f_bit22_29:8;
        OTP_UINT32 e_bit14_21:8;    
        OTP_UINT32 d_bit4_13:10;
        OTP_UINT32 c_bit2_3:2;  
        OTP_UINT32 b_bit1 :1;
        OTP_UINT32 a_bit0 :1;           

#endif #endif
    }bits;
}E1SlotCtrl;

/*CPU  big little endian  test*/
void test_cpu_big_little_endian()
{
    OTP_UINT16  test_data16 =0;
    OTP_UINT8   x0 = 0;
    OTP_UINT8   x1 = 0;
    OTP_UINT8   x2 = 0;
    OTP_UINT8   x3 = 0;
    OTP_UINT8   test_data8=0;
    OTP_UINT8   a_test_data8[4];
    
    OTP_UINT32  test_data32 =0;
    OTP_UINT32  test0_data32 =0;

    E1SlotCtrl g_test_32;

    test_data16 = 0x1122;
    x0 = ((OTP_UINT8*)&test_data16)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data16)[1]; /*高地址单元*/

    test_data8=*( (unsigned char*) &test_data16 );
    
    printf(SCRN_NEWLINE);
    printf(SCRN_NEWLINE);
    
    if(test_data8 ==0x11)
    {
        printf("    CPU = big-endian 大端"SCRN_NEWLINE);

    }
    else
    {
        printf("    CPU = little-endian  小端"SCRN_NEWLINE);
    }

    printf(SCRN_NEWLINE);
    printf("  test_data16 =0x1122 ,强制转换OTP_UINT8为:%x"SCRN_NEWLINE,test_data8);
    printf("  低地址单元 test_data16[0]:0x%x"SCRN_NEWLINE, x0);
    printf("  高地址单元 test_data16[1]:0x%x"SCRN_NEWLINE, x1);

    test_data32 = 0x12345678;
    x0 = ((OTP_UINT8*)&test_data32)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data32)[1]; /*低中地址单元*/
    x2 = ((OTP_UINT8*)&test_data32)[2]; /*高中地址单元*/
    x3 = ((OTP_UINT8*)&test_data32)[3]; /*高地址单元*/
    test_data8=*( (unsigned char*) &test_data32 );
    test_data16=*( (unsigned short*) &test_data32 );
    
    printf(SCRN_NEWLINE);
    printf("  test_data32 = 0x12345678 ,指针强制转换为OTP_UINT8为:0x%x"SCRN_NEWLINE,test_data8);
    printf("  test_data32 = 0x12345678 ,指针强制转换为OTP_UINT16为:0x%x"SCRN_NEWLINE,test_data16);  
    printf("  低地址单元 test_data32[0]:0x%x"SCRN_NEWLINE,x0);
    printf("  低中地址单元 test_data32[1]:0x%x"SCRN_NEWLINE, x1);
    printf("  高中地址单元 test_data32[2]:0x%x"SCRN_NEWLINE, x2);
    printf("  高地址单元 test_data32[3]:0x%x"SCRN_NEWLINE, x3);

    test_data32 = 0x12345678;
    test_data8 =(OTP_UINT8)test_data32;
    test_data16 =(OTP_UINT16)test_data32;
    
    printf(SCRN_NEWLINE);
    printf("  test_data32 = 0x12345678 ,数据强制转换为OTP_UINT8为:0x%x"SCRN_NEWLINE,test_data8);
    printf("  test_data32 = 0x12345678 ,数据强制转换为OTP_UINT16为:0x%x"SCRN_NEWLINE,test_data16);  

    test_data8 =0x12;
    test_data32 =(OTP_UINT32)test_data8;
    printf(SCRN_NEWLINE);   
    printf("  test_data8 = 0x12 ,数据强制转换为OTP_UINT32为:0x%x"SCRN_NEWLINE,test_data32);

    a_test_data8[0]=0x12;
    a_test_data8[1]=0x34;
    a_test_data8[2]=0x56;
    a_test_data8[3]=0x78;
    printf(SCRN_NEWLINE);
    printf("  test_data8 = 0x12 ,数据强制转换为OTP_UINT32为:0x%x"SCRN_NEWLINE,test_data32);
    printf("    a_test_data8[0]=0x%x"SCRN_NEWLINE,a_test_data8[0]);
    printf("    a_test_data8[1]=0x%x"SCRN_NEWLINE,a_test_data8[1]);
    printf("    a_test_data8[2]=0x%x"SCRN_NEWLINE,a_test_data8[2]);
    printf("    a_test_data8[3]=0x%x"SCRN_NEWLINE,a_test_data8[3]);

    test_data32 =(OTP_UINT32)((a_test_data8[0]<<24) + (a_test_data8[1]<<16) +(a_test_data8[2]<<8) +(a_test_data8[3]));
    printf("    test_data32 =(OTP_UINT32)((a_test_data8[0]<<24) + (a_test_data8[1]<<16) +(a_test_data8[2]<<8) +(a_test_data8[3])); \r\n");
    printf("  a_test_data8  ,数据强制转换为OTP_UINT32为:0x%x"SCRN_NEWLINE,test_data32); 

    test_data32 =((OTP_UINT32)(a_test_data8[0]<<24) + (OTP_UINT32)(a_test_data8[1]<<16) +(OTP_UINT32)(a_test_data8[2]<<8) +((OTP_UINT32)a_test_data8[3]));
    printf("    test_data32 =((OTP_UINT32)(a_test_data8[0]<<24) + (OTP_UINT32)(a_test_data8[1]<<16) +(OTP_UINT32)(a_test_data8[2]<<8) +((OTP_UINT32)a_test_data8[3]));  \r\n"); 
    printf("  a_test_data8  ,数据强制转换为OTP_UINT32为:0x%x"SCRN_NEWLINE,test_data32); 

    test_data32 =a_test_data8[0];
    test_data32 <<=8;
    test_data32 +=a_test_data8[1];
    test_data32 <<=8;
    test_data32 +=a_test_data8[2];
    test_data32 <<=8;
    test_data32 +=a_test_data8[3];

    printf("  a_test_data8  ,数据强制转换为OTP_UINT32为:0x%x"SCRN_NEWLINE,test_data32); 
    
    test_data32 = 0x12345678;
    
    a_test_data8[0] =(test_data32>>24);
    a_test_data8[1] =(test_data32>>16);
    a_test_data8[2] =(test_data32>>8);  
    a_test_data8[3] =(test_data32); 
    printf(SCRN_NEWLINE);   
    printf("    a_test_data8[0]=0x%x"SCRN_NEWLINE,a_test_data8[0]);
    printf("    a_test_data8[1]=0x%x"SCRN_NEWLINE,a_test_data8[1]);
    printf("    a_test_data8[2]=0x%x"SCRN_NEWLINE,a_test_data8[2]);
    printf("    a_test_data8[3]=0x%x"SCRN_NEWLINE,a_test_data8[3]);


    test_data32 = 0x12345678;
    
    a_test_data8[0] =(test_data32);
    a_test_data8[1] =(test_data32>>8);
    a_test_data8[2] =(test_data32>>16); 
    a_test_data8[3] =(test_data32>>24); 
    printf(SCRN_NEWLINE);   
    printf("    a_test_data8[0]=0x%x"SCRN_NEWLINE,a_test_data8[0]);
    printf("    a_test_data8[1]=0x%x"SCRN_NEWLINE,a_test_data8[1]);
    printf("    a_test_data8[2]=0x%x"SCRN_NEWLINE,a_test_data8[2]);
    printf("    a_test_data8[3]=0x%x"SCRN_NEWLINE,a_test_data8[3]);

    test_data32 = 0x00123456;
    x0 = ((OTP_UINT8*)&test_data32)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data32)[1]; /*低中地址单元*/
    x2 = ((OTP_UINT8*)&test_data32)[2]; /*高中地址单元*/
    x3 = ((OTP_UINT8*)&test_data32)[3]; /*高地址单元*/

    printf(SCRN_NEWLINE);   
    printf("  原数据test_data32 = 0x00123456 "SCRN_NEWLINE);
    printf("  低地址单元 test_data32[0]:0x%x"SCRN_NEWLINE,x0);
    printf("  低中地址单元 test_data32[1]:0x%x"SCRN_NEWLINE, x1);
    printf("  高中地址单元 test_data32[2]:0x%x"SCRN_NEWLINE, x2);
    printf("  高地址单元 test_data32[3]:0x%x"SCRN_NEWLINE, x3);

    test0_data32 = 0x00123456;
    test_data32 =(test0_data32<<4);
    
    x0 = ((OTP_UINT8*)&test_data32)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data32)[1]; /*低中地址单元*/
    x2 = ((OTP_UINT8*)&test_data32)[2]; /*高中地址单元*/
    x3 = ((OTP_UINT8*)&test_data32)[3]; /*高地址单元*/

    printf(SCRN_NEWLINE);
    printf("  test_data32 <<4 左移4bit :0x%x; "SCRN_NEWLINE,test_data32);
    printf("  低地址单元 test_data32[0]:0x%x"SCRN_NEWLINE,x0);
    printf("  低中地址单元 test_data32[1]:0x%x"SCRN_NEWLINE, x1);
    printf("  高中地址单元 test_data32[2]:0x%x"SCRN_NEWLINE, x2);
    printf("  高地址单元 test_data32[3]:0x%x"SCRN_NEWLINE, x3);

    test0_data32 = 0x00123456;
    test_data32 =(test0_data32>>4);
    
    x0 = ((OTP_UINT8*)&test_data32)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data32)[1]; /*低中地址单元*/
    x2 = ((OTP_UINT8*)&test_data32)[2]; /*高中地址单元*/
    x3 = ((OTP_UINT8*)&test_data32)[3]; /*高地址单元*/

    printf(SCRN_NEWLINE);   
    printf("  test_data32 >>4 右移4bit :0x%x; "SCRN_NEWLINE,test_data32);
    printf("  低地址单元 test_data32[0]:0x%x"SCRN_NEWLINE,x0);
    printf("  低中地址单元 test_data32[1]:0x%x"SCRN_NEWLINE, x1);
    printf("  高中地址单元 test_data32[2]:0x%x"SCRN_NEWLINE, x2);
    printf("  高地址单元 test_data32[3]:0x%x"SCRN_NEWLINE, x3);

    memset(&g_test_32,0,sizeof(g_test_32));

    printf(SCRN_NEWLINE);   
    printf("  g_test_32  :0x%x; "SCRN_NEWLINE,g_test_32.Byte);

    g_test_32.bits.a_bit0 =1;
    g_test_32.bits.b_bit1 =1;
    g_test_32.bits.c_bit2_3 =2;
    g_test_32.bits.d_bit4_13 =7;
    g_test_32.bits.e_bit14_21 =5;
    g_test_32.bits.f_bit22_29 =3;   
    g_test_32.bits.g_bit30 =0;      
    g_test_32.bits.h_bit31 =1;  
    
    printf("    g_test_32.bits.a_bit0 =1;     \r\n");
    printf("    g_test_32.bits.b_bit1 =1;     \r\n");
    printf("    g_test_32.bits.c_bit2_3 =2;  \r\n"); 
    printf("    g_test_32.bits.d_bit4_13 =7;       \r\n");
    printf("    g_test_32.bits.e_bit14_21 =5;  \r\n"); 
    printf("    g_test_32.bits.f_bit22_29 =3;    \r\n");
    printf("    g_test_32.bits.g_bit30 =0;      \r\n"); 
    printf("    g_test_32.bits.h_bit31 =1;      \r\n");
    
    printf(SCRN_NEWLINE);   
    printf("  g_test_32  :0x%x; "SCRN_NEWLINE,g_test_32.Byte);

    test_data32 = g_test_32.Byte;
    x0 = ((OTP_UINT8*)&test_data32)[0]; /*低地址单元*/
    x1 = ((OTP_UINT8*)&test_data32)[1]; /*低中地址单元*/
    x2 = ((OTP_UINT8*)&test_data32)[2]; /*高中地址单元*/
    x3 = ((OTP_UINT8*)&test_data32)[3]; /*高地址单元*/


    printf("  低地址单元 g_test_32[0]:0x%x"SCRN_NEWLINE,x0);
    printf("  低中地址单元 g_test_32[1]:0x%x"SCRN_NEWLINE, x1);
    printf("  高中地址单元 g_test_32[2]:0x%x"SCRN_NEWLINE, x2);
    printf("  高地址单元 g_test_32[3]:0x%x"SCRN_NEWLINE, x3);

    printf(SCRN_NEWLINE);   
}

在MPC852 和MPC8314上运行代码结果:
CPU = big-endian 大端

test_data16 =0x1122 ,强制转换OTP_UINT8为:11
低地址单元 test_data16[0]:0x11
高地址单元 test_data16[1]:0x22

test_data32 = 0x12345678 ,指针强制转换为OTP_UINT8为:0x12
test_data32 = 0x12345678 ,指针强制转换为OTP_UINT16为:0x1234
低地址单元 test_data32[0]:0x12
低中地址单元 test_data32[1]:0x34
高中地址单元 test_data32[2]:0x56
高地址单元 test_data32[3]:0x78

test_data32 = 0x12345678 ,数据强制转换为OTP_UINT8为:0x78
test_data32 = 0x12345678 ,数据强制转换为OTP_UINT16为:0x5678

test_data8 = 0x12 ,数据强制转换为OTP_UINT32为:0x12

test_data8 = 0x12 ,数据强制转换为OTP_UINT32为:0x12
a_test_data8[0]=0x12
a_test_data8[1]=0x34
a_test_data8[2]=0x56
a_test_data8[3]=0x0x78
test_data32 =(OTP_UINT32)((a_test_data8[0]<<24) + (a_test_data8[1]<<16) +(a_test_data8[2]<<8) +(a_test_data8[3]));
a_test_data8 ,数据强制转换为OTP_UINT32为:0x12345678
test_data32 =((OTP_UINT32)(a_test_data8[0]<<24) + (OTP_UINT32)(a_test_data8[1]<<16) +(OTP_UINT32)(a_test_data8[2]<<8) +((OTP_UINT32)a_test_data8[3]));
a_test_data8 ,数据强制转换为OTP_UINT32为:0x12345678
a_test_data8 ,数据强制转换为OTP_UINT32为:0x12345678

    a_test_data8[0]=0x12
    a_test_data8[1]=0x34
    a_test_data8[2]=0x56
    a_test_data8[3]=0x78

    a_test_data8[0]=0x78
    a_test_data8[1]=0x56
    a_test_data8[2]=0x34
    a_test_data8[3]=0x12

原数据test_data32 = 0x00123456
低地址单元 test_data32[0]:0x0
低中地址单元 test_data32[1]:0x12
高中地址单元 test_data32[2]:0x34
高地址单元 test_data32[3]:0x56

test_data32 <<4 左移4bit :0x1234560;
低地址单元 test_data32[0]:0x1
低中地址单元 test_data32[1]:0x23
高中地址单元 test_data32[2]:0x45
高地址单元 test_data32[3]:0x60

test_data32 >>4 右移4bit :0x12345;
低地址单元 test_data32[0]:0x0
低中地址单元 test_data32[1]:0x1
高中地址单元 test_data32[2]:0x23
高地址单元 test_data32[3]:0x45

g_test_32 :0x0;
g_test_32.bits.a_bit0 =1;
g_test_32.bits.b_bit1 =1;
g_test_32.bits.c_bit2_3 =2;
g_test_32.bits.d_bit4_13 =7;
g_test_32.bits.e_bit14_21 =5;
g_test_32.bits.f_bit22_29 =3;
g_test_32.bits.g_bit30 =0;
g_test_32.bits.h_bit31 =1;

g_test_32 :0xe01c140d;
低地址单元 g_test_32[0]:0xe0
低中地址单元 g_test_32[1]:0x1c
高中地址单元 g_test_32[2]:0x14
高地址单元 g_test_32[3]:0xd

在SPEAr310 上运行代码结果:
CPU = little-endian 小端

test_data16 =0x1122 ,强制转换OTP_UINT8为:22
低地址单元 test_data16[0]:0x22
高地址单元 test_data16[1]:0x11

test_data32 = 0x12345678 ,指针强制转换为OTP_UINT8为:0x78
test_data32 = 0x12345678 ,指针强制转换为OTP_UINT16为:0x5678
低地址单元 test_data32[0]:0x78
低中地址单元 test_data32[1]:0x56
高中地址单元 test_data32[2]:0x34
高地址单元 test_data32[3]:0x12

test_data32 = 0x12345678 ,数据强制转换为OTP_UINT8为:0x78
test_data32 = 0x12345678 ,数据强制转换为OTP_UINT16为:0x5678
test_data8 = 0x12 ,数据强制转换为OTP_UINT32为:0x12
test_data8 = 0x12 ,数据强制转换为OTP_UINT32为:0x12

a_test_data8[0]=0x12
a_test_data8[1]=0x34
a_test_data8[2]=0x56
a_test_data8[3]=0x78
test_data32 =(OTP_UINT32)((a_test_data8[0]<<24) + (a_test_data8[1]<<16) +(a_test_data8[2]<<8) +(a_test_data8[3]));
a_test_data8 ,数据强制转换为OTP_UINT32为:0x12345678
test_data32 =((OTP_UINT32)(a_test_data8[0]<<24) + (OTP_UINT32)(a_test_data8[1]<<16) +(OTP_UINT32)(a_test_data8[2]<<8) +((OTP_UINT32)a_test_data8[3]));
a_test_data8 ,数据强制转换为OTP_UINT32为:0x12345678
a_test_data8 ,数据强制转换为OTP_UINT32为:0x12345678

a_test_data8[0]=0x12
a_test_data8[1]=0x34
a_test_data8[2]=0x56
a_test_data8[3]=0x78
a_test_data8[0]=0x78
a_test_data8[1]=0x56
a_test_data8[2]=0x34
a_test_data8[3]=0x12

原数据test_data32 = 0x00123456
低地址单元 test_data32[0]:0x56
低中地址单元 test_data32[1]:0x34
高中地址单元 test_data32[2]:0x12
高地址单元 test_data32[3]:0x0

test_data32 <<4 左移4bit :0x1234560;
低地址单元 test_data32[0]:0x60
低中地址单元 test_data32[1]:0x45
高中地址单元 test_data32[2]:0x23
高地址单元 test_data32[3]:0x1

test_data32 >>4 右移4bit :0x12345;
低地址单元 test_data32[0]:0x45
低中地址单元 test_data32[1]:0x23
高中地址单元 test_data32[2]:0x1
高地址单元 test_data32[3]:0x0

g_test_32 :0x0;
g_test_32.bits.a_bit0 =1;
g_test_32.bits.b_bit1 =1;
g_test_32.bits.c_bit2_3 =2;
g_test_32.bits.d_bit4_13 =7;
g_test_32.bits.e_bit14_21 =5;
g_test_32.bits.f_bit22_29 =3;
g_test_32.bits.g_bit30 =0;
g_test_32.bits.h_bit31 =1;
g_test_32 :0x80c1407b;

低地址单元 g_test_32[0]:0x7b
低中地址单元 g_test_32[1]:0x40
高中地址单元 g_test_32[2]:0xc1
高地址单元 g_test_32[3]:0x80

你可能感兴趣的:(大端小端问题总结)