在嵌入式軟件編程中深入理解關(guān)鍵字
與其他RISC架構一樣,ARM處理器能夠高效地訪(fǎng)問(wèn)對齊的數據,即字地址的末尾兩位為零,半字地址的最后一位為零,也稱(chēng)這樣的數據位于它的自然大小邊界或者是自然對齊的。ARM編譯器希望普通的“C”指針指向一個(gè)4字節對齊內存地址,這樣它可以在代碼中使用LDR/STR指令一次操作4個(gè)字節,否則只能使用LDRB/LDRH等字節/半字操作指令。相反如果指針指向一個(gè)非自然對齊的地址,例如如果一個(gè)整型指針指向地址0x8006,當然希望裝載地址0xS006-0xS007-0x8008-0xS009處的數據,但是實(shí)際上ARM會(huì )對非自然對齊的地址進(jìn)行轉換而從裝載地址0xS004-0xS005-0x8006-0xS007處的數據。在下面的示例中(測試環(huán)境為uVision3),首先定義了一個(gè)大小為16字節的整型數組,依次初始化為0,1,2,…,15。由于array是一個(gè)整型數組,編譯器會(huì )確保它是4字節對齊的,即指針pc指向一個(gè)4字節對齊的地址。運行程序后,可以看到如果對pc指針不加__packed標記進(jìn)行修飾,將得到一個(gè)奇怪的0x01000302;而在添加了__packed關(guān)鍵字之后,就得到了正確的結果。也就是說(shuō),如果要訪(fǎng)問(wèn)非自然對齊的數據,必須使用__packed關(guān)鍵字顯式地標記出來(lái)。本文引用地址:http://dyxdggzs.com/article/152278.htm
ARM編譯器總是保證程序中的變量、結構體或聯(lián)合中的域分配到自然對齊的地址。這意味著(zhù)編譯器經(jīng)常需要在各個(gè)域之間插入填充,以確保每個(gè)域的自然對齊。通常來(lái)說(shuō),程序員可以對這些填充視而不見(jiàn),但是也有例外,例如為了節省結構體占用的空間,可以利用__packed去除填充。在了解了編譯器的填充行為之后,可以通過(guò)調整域的順序來(lái)減小結構體占用的空間。例如雖然結構體s1和s2的域相同,但是sizeof(s1)等于16,而sizeof(s2)等于12。
評論