移植驅動代碼時發現工程中使用了如下形式的代碼
typedef struct BlkTestTag{
uint16_tm_u1Var1;
uint8_t reserve[2];
uint32_tm_u4Var2;
}BlkTest;
uint8_t test_array[8] ={0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};
pblkTest = (BlkTest *)test_array;
u2Var1 = pblkTest->m_u1Var1;
u4Var2 = pblkTest->m_u4Var2;
本意是為了將結構體的值以數組常量形式給出。
讓var1 = 0x0201; var2 =0x08070605
再將這些代碼移植到另一款MCU時發現工作不正常。之後發現移植的這款MCU是大端的,而我們之前的使用的MCU都是小端的。於是定位上上面的數組賦值代碼。
在小端MCU下會按我們想要的結果來賦值,如下圖。Var1和var2的結果是我們想要的。
但是如果再大端MCU上執行的話結果就大不一樣。
原因在於數組uint8_t test_array[8] = {0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};
其數據在內存中是從低地址到高地址存放的,如下圖
即0x20000000地址處為0x01, 0x20000000地址處為0x02……
所以直接將數組名轉換成結構體指針後,在訪問m_u1Var1成員時,該成員為2字節無符號整型,所以他會將0x20000000 和0x20000001 地址處的兩個值當做 m_u1Var1
所以如果是小端MCU 低地址0x20000000的值0x01會被解釋為低字節
高地址0x20000001的值0x02會被解釋為高字節
於是值就是 0x0201
如果是大端MCU 低地址0x20000000的值0x01會被解釋為高字節
高地址0x20000001的值0x02會被解釋為低字節
於是值就是 0x0102
這個數組到結構體的轉換問題,在知道了大小端後問題定位還比較容易。
另一個關於聯合體的問題就有點偏,即字節內的bit序在大小端MCU上也是不同的。
工程中存在如下代碼
typedef union UnTestTag{
uint8_tvar;
struct{
uint8_tbit0:1;
uint8_tbit1:1;
uint8_tbit2:1;
uint8_tbit3:1;
uint8_tbit4:1;
uint8_tbit5:1;
uint8_tbit6:1;
uint8_tbit7:1;
}pixels;
}UnTest;
在對聯合體賦值後
unTest.var = 0x11; 二進制值為 00010001
上面的聯合體定義就是為了判斷某些位,所以我們希望的是賦值0x11後,位段的unTest.pixels.bit0和unTest.pixels.bit4的值應該為1 才對。
即我們希望的是名字能反應真正的bit值
在小端MCU中運行時的確是正確的。
但是在大端MCU中運行時結果如下圖。
即聯合體中 unTest.pixels.bit0的值反應的不再是真正的二進制中的bit0了
反而是unTest.pixels.bit7 反應的是真正的bit0.
即unTest.pixels.bit0- unTest.pixels.bit7 反應的真實值其實是bit7-bit0了
但是這裡的 << 實際操作是向bit0方向移位了
附上一段簡單測試代碼,在keil工程中 選擇模擬器調試
然後勾選big endian的情況下 debug實例代碼,然後打端點查看變量值,結果就是大端情形下的。不勾選 big endian 再debug跑一次就是小端情形下的
typedef struct BlkTestTag{
uint16_t m_u1Var1;
uint8_t reserve[2];
uint32_t m_u4Var2;
}BlkTest;
uint8_t test_array[8] = {0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};
typedef union UnTestTag{
uint8_t var;
struct{
uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
}pixels;
}UnTest;
BlkTest *pblkTest;
uint16_t u2Var1;
uint32_t u4Var2;
UnTest unTest;
int main(void){
pblkTest = (BlkTest *)test_array;
u2Var1 = pblkTest->m_u1Var1;
u4Var2 = pblkTest->m_u4Var2;
unTest.var = 0x11;