- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- C++中結構體對齊規則的示例分析
這篇文章主要介紹了C++中結構體對齊規則的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著(zhù)大家一起了解一下。
CPU一次能讀取多少個(gè)字節的數據主要是看數據總線(xiàn)是多少位的,16位CPU一次能讀取2個(gè)字節,32位CPU一次能讀取4個(gè)字節,64位CPU一次能讀取8個(gè)字節。并且不能跨內存區間訪(fǎng)問(wèn),這句話(huà)的意思可以理解為,如果CPU是32位的話(huà),那么可以將整個(gè)內存區間每4個(gè)字節分為一塊(BLOCK),每次讀取一個(gè)BLOCK的數據。
那么對于下面這個(gè)結構體:
struct st { char c; int i; };
如果不進(jìn)行對齊操作,char 的地址范圍0x00000000,int的地址范圍為0x00000001----0x00000004,int分布在兩個(gè)不同的BLOCK上,因此要讀取int需要兩次操作;如果進(jìn)行4字節對齊,那么int的地址范圍為0x00000004----0x00000007,處在一個(gè)BLOCK上,因此只需一次讀取操作即可。缺點(diǎn)也顯而易見(jiàn),多占用了3個(gè)字節。這也是典型的一種空間換時(shí)間的方法吧。
結構體對齊需要滿(mǎn)足以下三條規則,其中系統對齊模數在64位機器上默認為8字節,32位機器上默認為4字節。通過(guò)預處理指令#pargma pack(N)可以修改系統模數為N個(gè)字節。
1、以結構體第一個(gè)元素的地址為起始地址,亦即結構體的起始地址。由上可知,第一個(gè)元素的偏移量為0;
2、結構體元素對齊原則:結構體成員的對齊模數為類(lèi)型大小與系統對齊模數的較小者;結構體成員的偏移量(填充)為對齊模數的整數倍。
3、結構體大小對齊原則:結構體的對齊模數為結構體最大元素與系統對齊模數的較小者;結構體的大?。ㄌ畛洌榻Y構體對齊模數的整數倍。
測試環(huán)境為64位Windows ,VS2019,定義結構體st1,包含3個(gè)元素char,int,double,定義系統對齊模數為4個(gè)字節。
#include <iostream> #pragma pack(4) using Tsize = unsigned long long; using namespace std; struct st1 { char c; int i; double db; Tsize ch_offset() { return Tsize((Tsize)&this->c - (Tsize)this); } Tsize int_offset() { return Tsize((Tsize)&this->i - (Tsize)this); } Tsize double_offset() { return Tsize((Tsize)&this->db - (Tsize)this); } }; int main() { cout << "st1結構體大小" << sizeof(st1) << endl; cout << "char 偏移量=" << st1().ch_offset() << endl; cout << "int偏移量=" << st1().int_offset() << endl; cout << "double偏移量=" << st1().double_offset() << endl; return 0; }
首先我們按照對齊規則來(lái)進(jìn)行分析。第一個(gè)元素為char,類(lèi)型大小為1個(gè)字節,對齊模數min(1,4)=1,偏移量為0是對齊模數的整數倍,無(wú)需填充(從這里我們可以看到,第一個(gè)字節偏移量始終為0,是不需要填充的),下一個(gè)元素的偏移從1開(kāi)始;第二個(gè)元素為int,類(lèi)型大小4個(gè)字節,對齊模數為4個(gè)字節,不填充時(shí)偏移量為1,不是4的整數倍,因此這里需要填充3個(gè)字節,使得int的偏移量為4,且下一個(gè)元素偏移從8開(kāi)始;第三個(gè)元素是double,類(lèi)型大小為8個(gè)字節,對齊模數為4,偏移量從8開(kāi)始,是4的整數倍,因此無(wú)需填充,占用8個(gè)字節,因此結構體的大小為16個(gè)字節。運行程序輸出:
將系統對齊模數修改為1 【#pargma pack(1)】,這樣的話(huà),任何情況下都無(wú)需填充(不足一個(gè)字節的類(lèi)型視為一個(gè)字節),結構體的大小即為結構體元素大小之和。運行程序輸出:
將系統對齊模數修改為8 【#pargma pack(8)】,這樣的話(huà),任何情況下都無(wú)需填充(不足一個(gè)字節的類(lèi)型視為一個(gè)字節),結構體的大小即為結構體元素大小之和。運行程序輸出:
Emmm,好像和系統對齊模數為4時(shí)沒(méi)什么變化。那我們將int 和 double的順序換一下呢?
#include <iostream> #pragma pack(8) using Tsize = unsigned long long; using namespace std; struct st1 { char c; double db; int i; Tsize ch_offset() { return Tsize((Tsize)&this->c - (Tsize)this); } Tsize int_offset() { return Tsize((Tsize)&this->i - (Tsize)this); } Tsize double_offset() { return Tsize((Tsize)&this->db - (Tsize)this); } }; int main() { cout << "st1結構體大小" << sizeof(st1) << endl; cout << "char 偏移量=" << st1().ch_offset() << endl; cout << "double偏移量=" << st1().double_offset() << endl; cout << "int偏移量=" << st1().int_offset() << endl; return 0; }
順序調了下,結構體就比原來(lái)大了8個(gè)字節!!!從中我們可以看出,將結構體元素從小到大排列,可以最大程度節省空間。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站