大端小端問題總結

大小端介紹問題總結

一、簡介大小端定義

  • 大端模式
    所謂的大端模式,是指數據的低位(就是權值較小的后面那幾位)保存在內存的高地址中,而數據的高位,保存在內存的低地址中,這樣的存儲模式有點兒類似于把數據當作字符串順序處理:地址由小向大增加,而數據從高位往低位放;
  • 小端模式
    所謂的小端模式,是指數據的低位保存在內存的低地址中,而數據的高位保存在內存的高地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和我們的邏輯方法一致。

例子:在內存中雙字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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容