最近看到一些朋友在交流結構體對齊方面的一些問題,從他們的交談中隱隱約感覺有幾個朋友對結構體成員的對齊理解上有點偏差,不能說完全不對吧,畢竟這是老生常談的問題了~
1、變量與內存
首先我們要明確,在嵌入式C語言中變量是什么?其實所謂的變量就是一小段內存。
當你隨心所欲的在C程序中定義著各種變量,有沒有想過他們是如何被安排到相應內存上的?
好吧,其實他們是怎么安排的,并不需要程序員太多的操心,這個映射過程都是編譯器自動給大家分配的,(可以借助動態內存的角度去看待這個分配問題),因為大部分變量在一定內存區域上是可以任意選擇地址的,比如你定義一個全局的int gVar 變量,在不進行特殊指定內存位置的情況下,其編譯后所分配的內存地址并不一定每次都是相同的;當然,每次編譯完成便會確定下來,并且程序中對該變量的訪問,均會使用所確定下來的內存地址。
既然變量的地址分配過程由編譯器自動完成,但有時候我們想把一些或者某個變量放在固定的內存地址處等,此時就需要通過一些語法來告訴編譯器該如何分配這些指定變量內存的分配,比如要做復位數據恢復等。
然而內存的對齊問題也是對這些變量分配位置處理的一種方式,通常我們看到的align或者pack等就是來干預編譯器的這塊處理的。
2、結構體對齊
理解了上面的一個思路,那么我們來分析分析結構體對齊問題。
參考demo:
運行結果:
以上編譯結果采用的是32位編譯器,默認對齊方式是4個字節,char類型占據1個字節,int占據4個字節,
下面簡單分析一下結果:
1、默認方式,采用4個字節對齊,那么char后面需要填充3個字節,然后存放int類型,所以結構體大小輸出為8。
2、1字節對齊方式,直接緊湊排列,很多人也叫不進行對齊處理,所以輸出結果是5。
3、2字節對齊方式,其實和4個字節對齊是類似的,char按照2字節對齊,所以后面需要填充一個字節,這樣int才能以兩字節對齊排布,此時整個結構體占據6個字節。
4、4字節對齊方式與默認對齊方式一致,最后看看8字節對齊,此時char類型與int類型完全能夠被8個字節容納,而該結構體最大數據類型是4個字節,所以char后面會預留3個字節,進行4字節對齊,然后放置int類型,此時與4字節對齊是一致的。那么一些朋友會問,是不是在上面的8字節例子中再加入一個char類型的成員,整個結構體就會占據16個字節了呢?
其輸出結果如下:
結構體所占據的字節是12個,那是不是認為8字節對齊沒有意義呢?我們再看一個實驗:
此時double占據了8個字節,按照前面的思路應該是4+8+4,應該最終結構體的大小是16個字節,而結果顯示:
輸出結果顯示24=8+8+8的形式,大家也可以直接采用打印結構體成員地址的辦法查看是幾個字節對齊,有點暈,到底編譯器這一塊是怎么處理的呢?結論是:對齊字節數 = min<當前指定的pack值,最大成員所占字節大小>。
很多朋友其實研究到這個階段基本上就沒有再繼續探究了~嵌入式C語言一定要跟硬件結合理解~
3、內存對齊
其實所謂的結構體對齊,并不是簡單的1個字節、兩個字節等多個字節的排列組合,而是在對應對齊地址上分布。首先對齊需要解決的問題是什么 ? 即為啥需要對齊?
提高內存的訪問效率,也可以說是受CPU等硬件方面的限制,按照特定的對齊地址進行數據的訪問要快于跨非對齊地址的內存訪問;并且有些平臺僅支持對齊方式訪問,非對齊方式會直接運行錯誤。
為了加快相關數據的正確訪問,編譯器會把相關的變量盡量的放到對齊的地址上,也就是默認的對齊方式,比如CPU在偶數地址上訪問比較快,那么就會采用2個字節對齊的方式。
所以結構體內部成員并不是簡單成員字節個數的對齊拼湊,而是讓結構體成員落在對齊的地址上以便訪問。如下圖所示,當進行2字節對齊,如果只是簡單的拼湊,兩種分布都是可以的,但是左側才是正確的2字節對齊方式,char成員變量的地址是2,int變量的地址是4,均為2字節的倍數。
總結一下: 結構體對齊不再是簡單的字節個數的拼湊,而是要與內存地址進行掛鉤~一般我們也可以理解為內存地址分配是多少字節的倍數,就是多少直接對齊~
審核編輯:劉清
-
嵌入式
+關注
關注
5096文章
19189瀏覽量
308031 -
cpu
+關注
關注
68文章
10911瀏覽量
213152 -
C語言
+關注
關注
180文章
7615瀏覽量
137855 -
編譯器
+關注
關注
1文章
1642瀏覽量
49318
發布評論請先 登錄
相關推薦
Orcad繪制原理圖的元器件對齊方法
![Orcad繪制原理圖的元器件<b class='flag-5'>對齊</b>方法](https://file1.elecfans.com/web3/M00/07/5F/wKgZPGelcaCAKwfGAAAOpk8Mx1M157.png)
ADR4520的負載調整度有點偏差是什么原因引起的?
KiCad的對齊工具不好用?
![KiCad的<b class='flag-5'>對齊</b>工具不好用?](https://file1.elecfans.com//web1/M00/F4/D2/wKgZoWcy166AZBlZAAFk4Vjf3gI929.png)
ARM嵌入式系統中內存對齊的重要性
![ARM嵌入式系統中內存<b class='flag-5'>對齊</b>的重要性](https://file1.elecfans.com/web2/M00/0B/50/wKgZomcxzEKACT3LAAA1HNJVj_w907.png)
ota升級的庫中,結構體upgrade_server_info中pespconn的作用是什么?
聚徽觸控-工控一體機和 PLC 一體機有什么不同
嵌入式中C語言結構體基本實現
![嵌入式中C語言<b class='flag-5'>結構</b><b class='flag-5'>體</b>基本實現](https://file1.elecfans.com//web2/M00/E4/42/wKgZomY_FOKAdlRXAADOabNodfI522.jpg)
評論