一、問(wèn)題來(lái)源 且看下面一段代碼: char buff[8] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xbc, 0xcd}; int v32, *p32; short v16, *p16; p32 = (int*)&( buff[1] ); p16 = (short*)&( buff[1] ); v32 = *p32; v16 = *p16; 我們來(lái)看看在ADS1.2編譯后,執(zhí)行的結(jié)果如下: v32 = 0x12785634 v16 = 0x1234 不管數(shù)據(jù)模式是大端結(jié)構(gòu),還是小端結(jié)構(gòu),結(jié)果都不對(duì)。 二、分析原因默認(rèn)情況下,ADS編譯器使用的是數(shù)據(jù)類型的自然邊界對(duì)其方式。數(shù)據(jù)的自然對(duì)其方式是指:如果該數(shù)據(jù)類型是n個(gè)字節(jié)的,那么該數(shù)據(jù)類型就按n字節(jié)對(duì)齊。例如: 1.、Usigned char 是1字節(jié)的,那么數(shù)據(jù)就按1字節(jié)對(duì)齊。 定義兩個(gè)變量如下: usigned char a08,b08; 如果a08所在的地址為,0x80000002,則b08所在的地址為0x80000003,兩個(gè)變量是連續(xù)分配的。 2、Usigned short 是2字節(jié)的,那么數(shù)據(jù)就按2字節(jié)對(duì)齊。 定義兩個(gè)變量如下: usigned char a08; Usigned short a16; 如果a08所在的地址為0x80000002,那么a16所在的地址為0x80000004,a16不會(huì)分配到0x80000003,默認(rèn)情況下,編譯器為usigned short類型的變量分配到2的倍數(shù)的地址處。 2、usigned long 是4字節(jié)的,那么數(shù)據(jù)就按4字節(jié)對(duì)齊。 定義兩個(gè)變量如下: usigned char a08; Usigned long a32 如果a08所在的地址為0x80000005,那么a16所在的地址為0x80000008,a32不會(huì)分配到0x80000006,默認(rèn)情況下,編譯器為usigned long類型的變量分配到4的倍數(shù)的地址處。 三、解決辦法 如果我們想要讓編譯器不使用自然邊界對(duì)齊,讓任何類型的變量都緊接著上一變量的地址進(jìn)行分配,可以使用__packed關(guān)鍵字。 四、使用__packed的注意事項(xiàng)1、__packed 對(duì)局部變量無(wú)效。 2、聲明為_(kāi)_packed 的變量,必須使用__packed 的指針變量來(lái)指向其地址。 如: __packed u16 u16a; __packed u16 *pu16; pu16 = (u16 *)&u16a; 3、聲明為_(kāi)_packed 的結(jié)構(gòu) 聲明為_(kāi)_packed 的結(jié)構(gòu)僅僅 4、聲明為_(kāi)_packed 的結(jié)構(gòu)變量 五、后記以上內(nèi)容未經(jīng)測(cè)試,由ADS編譯器手冊(cè)及相關(guān)資料理解總結(jié)所得。 不建議使用__packed 來(lái)節(jié)省數(shù)據(jù)大小,因?yàn)檫@需要付出減低執(zhí)行效率和浪費(fèi)代碼空間的代價(jià)。 更多交流可以加Q啊2685896890
|