瞭解#pragma pack(n)

    早上看書,看到#pragma pack(n),不甚瞭解,果斷學習之,留點心得體會,大家一起討論討論

 

例子,一般的題目主要是問sizeof(S1)是多少:

 

1.當n大於結構體最長的數據類型的長度時(如例子當中的int),這個n就宣佈沒有任何影響了

2.計算大小和補字節時從前往後計算,對齊按數據類型和n值當中的小的值進行,如char是1,如果n是4的話,那麼以1做對齊,當加入一個新的成員時,這個成員的起始偏移必須是其對齊值的整數倍.好吧,比較抽象,舉例來說,假設n=4,如S1,算大小時這麼算,首先是m1,m1是char,一個字節,用1個字節對齊,加上m2時,m2是short,兩個字節,那麼此時,m2的起始偏移是2,偏移是從0算起的.此時就需要補一個字節[m1,00,(m2,m2)],進而加入m4,剛好是4個字節,同時起始偏移是4,很好,接下來3個char,最後由於以4對齊,所以還要補多一個字節,總的結構體的長度是12.如果n=8,那麼8>int的長度,所以結構體以4個字節進行對齊.如果n=1,就是要求不做對齊處理,結構體長度爲10.

3.當結構體當中存在結構體成員,那麼結構體成員按他的長度參與對齊,比如我現在有個S2的結構,裏面有個S1結構的成員,如果我聲明S1的時候n=1,那麼在S2裏面S1以10的長度參與對齊,如果聲明S1的n=4,那麼S2裏面,S1以長度12對齊.需要注意的是,S1結構體的成員以幾個字節的形式對齊要看n值與S1的int誰比較小.這個注意點主要是在判斷內部成員內存位置的時候需要用到.

 

有個題目我覺得分析的不錯,附上給大家

-----------------------------------------------我是分割線--------------------------------------------------


1.sizeof(s2) = ?
2.s2的c後面空了幾個字節接着是d?

 

sizeof(S2)結果爲24.
成員對齊有一個重要的條件,即每個成員分別對齊.即每個成員按自己的方式對齊.
也就是說上面雖然指定了按8字節對齊,但並不是所有的成員都是以8字節對齊.其對齊的規則是,每個成員按其類型的對齊參數(通常是這個類型的大小)和指定對齊參數(這裏是8字節)中較小的一個對齊.並且結構的長度必須爲所用過的所有對齊參數的整數倍,不夠就補空字節.
S1中,成員a是1字節默認按1字節對齊,指定對齊參數爲8,這兩個值中取1,a按1字節對齊;成員b是4個字節,默認是按4字節對齊,這時就按4字節對齊,所以sizeof(S1)應該爲8;
S2中,c和S1中的a一樣,按1字節對齊,而d 是個結構,它是8個字節,它按什麼對齊呢?對於結構來說,它的默認對齊方式就是它的所有成員使用的對齊參數中最大的一個,S1的就是4.所以,成員d就是按4字節對齊.成員e是8個字節,它是默認按8字節對齊,和指定的一樣,所以它對到8字節的邊界上,這時,已經使用了12個字節了,所以又添加了4個字節的空,從第16個字節開始放置成員e.這時,長度爲24,已經可以被8(成員e按8字節對齊)整除.這樣,一共使用了24個字節.
                          a    b
S1的內存佈局:11**,1111,
                          c    S1.a S1.b     d
S2的內存佈局:1***,11**,1111,****11111111

這裏有三點很重要:
1.每個成員分別按自己的方式對齊,並能最小化長度
2.複雜類型(如結構)的默認對齊方式是它最長的成員的對齊方式,這樣在成員是複雜類型時,可以最小化長度
3.對齊後的長度必須是成員中最大的對齊參數的整數倍,這樣在處理數組時可以保證每一項都邊界對齊

補充一下,對於數組,比如:
char a[3];這種,它的對齊方式和分別寫3個char是一樣的.也就是說它還是按1個字節對齊.
如果寫: typedef char Array3[3];
Array3這種類型的對齊方式還是按1個字節對齊,而不是按它的長度.
不論類型是什麼,對齊的邊界一定是1,2,4,8,16,32,64....中的一個.

發佈了37 篇原創文章 · 獲贊 4 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章