本文為本人另一個(gè)賬號(hào)上的文章,那個(gè)賬號(hào)不要了,乾坤大挪移過(guò)來(lái)
。
最近遇到結(jié)構(gòu)體內(nèi)存對(duì)齊的問(wèn)題,發(fā)現(xiàn)自己一知半解,于是在網(wǎng)上搜集了些資料,總結(jié)如下。
一、規(guī)則
每個(gè)特定平臺(tái)上的編譯器都有自己的默認(rèn)“對(duì)齊系數(shù)”(也叫對(duì)齊模數(shù))。程序員可以通過(guò)預(yù)編譯命令#pragma pack(n),n=1,2,4,8,16來(lái)改變這一系數(shù),其中的n就是你要指定的“對(duì)齊系數(shù)”,VC++默認(rèn) n = 8。對(duì)齊分兩步,第一步:數(shù)據(jù)成員對(duì)齊;第二步:結(jié)構(gòu)體對(duì)齊。
- 數(shù)據(jù)成員對(duì)齊: 每個(gè)結(jié)構(gòu)體成員所分配的存儲(chǔ)位置與起始點(diǎn)的偏移量必須能夠整除min(對(duì)齊系數(shù),成員字節(jié)數(shù))。
- 結(jié)構(gòu)(或聯(lián)合)的整體對(duì)齊: 整個(gè)結(jié)構(gòu)體所占存儲(chǔ)空間要能整除min(max(成員字節(jié)數(shù)),對(duì)齊系數(shù))。
綜合上面兩點(diǎn)規(guī)則推斷:當(dāng)所有數(shù)據(jù)成員長(zhǎng)度 都 小于 #pragma pack的n值時(shí),這個(gè)n值的大小將不產(chǎn)生任何效果。
二、實(shí)例說(shuō)明
為節(jié)省時(shí)間,只舉例說(shuō)明“對(duì)齊系數(shù)”為 2 和 8 時(shí)的情形。
(一)對(duì)齊系數(shù)為2
1、成員數(shù)據(jù)對(duì)齊。
#pragma pack(2) struct test_t { int a; /* 長(zhǎng)度4 > 2 按2對(duì)齊;起始o(jì)ffset=0 0%2=0;存放位置區(qū)間[0,3] */ char b; /* 長(zhǎng)度1 < 2 按1對(duì)齊;起始o(jì)ffset=4 4%1=0;存放位置區(qū)間[4] */ short c; /* 長(zhǎng)度2 = 2 按2對(duì)齊;起始o(jì)ffset=6 6%2=0;存放位置區(qū)間[6,7] ,前面空了一個(gè)字節(jié)*/ char d; /* 長(zhǎng)度1 < 2 按1對(duì)齊;起始o(jì)ffset=8 8%1=0;存放位置區(qū)間[8] */ }; #pragma pack()
成員總大小= 9
2、整體對(duì)齊
整體對(duì)齊系數(shù) = min((max(int,short,char), 2) = 2
整體大小(size)=$(成員總大小) 按 $(整體對(duì)齊系數(shù)) 圓整 = 10 /* 10%2=0 */
為了更好地說(shuō)明問(wèn)題,下面調(diào)換一下c和d的位置,再看一下對(duì)齊情況。
1、成員數(shù)據(jù)對(duì)齊。
#pragma pack(2) struct test_t { int a; /* 長(zhǎng)度4 > 2 按2對(duì)齊;起始o(jì)ffset=0 0%2=0;存放位置區(qū)間[0,3] */ char b; /* 長(zhǎng)度1 < 2 按1對(duì)齊;起始o(jì)ffset=4 4%1=0;存放位置區(qū)間[4] */ char d; /* 長(zhǎng)度1 < 2 按1對(duì)齊;起始o(jì)ffset=8 8%1=0;存放位置區(qū)間[5] */ short c; /* 長(zhǎng)度2 = 2 按2對(duì)齊;起始o(jì)ffset=6 6%2=0;存放位置區(qū)間[6,7] */ }; #pragma pack()
成員
總大小 = 8
2、整體對(duì)齊
整體對(duì)齊系數(shù) = min((max(int,short,char), 2) = 2
整體大小(size)=$(成員總大小) 按 $(整體對(duì)齊系數(shù)) 圓整 = 8 /* 8%2=0 */
整體大小(size)=$(成員總大小) 按 $(整體對(duì)齊系數(shù)) 圓整 = 8 /* 8%2=0 */
(二) 對(duì)齊系數(shù)為8
1、成員數(shù)據(jù)對(duì)齊。
#pragma pack(8) struct test_t { int a; /* 長(zhǎng)度4 < 8 按4對(duì)齊;起始o(jì)ffset=0 0%4=0;存放位置區(qū)間[0,3] */ char b; /* 長(zhǎng)度1 < 8 按1對(duì)齊;起始o(jì)ffset=4 4%1=0;存放位置區(qū)間[4] */ short c; /* 長(zhǎng)度2 < 8 按2對(duì)齊;起始o(jì)ffset=6 6%2=0;存放位置區(qū)間[6,7] ,前面空一個(gè)字節(jié)*/ char d; /* 長(zhǎng)度1 < 8 按1對(duì)齊;起始o(jì)ffset=8 8%1=0;存放位置區(qū)間[8] */ }; #pragma pack()
成員總大小 = 9
2、整體對(duì)齊
整體對(duì)齊系數(shù) = min((max(int,short,char),8) = 4
整體大小(size)=$(成員總大小) 按 $(整體對(duì)齊系數(shù)) 圓整 = 12/* 12%4=0 */
整體大小(size)=$(成員總大小) 按 $(整體對(duì)齊系數(shù)) 圓整 = 12/* 12%4=0 */
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
