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