溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解決C++結構體內(nèi)存對齊計算問題

發(fā)布時間:2021-09-16 09:47:32 來源:億速云 閱讀:108 作者:柒染 欄目:編程語言

這篇文章將為大家詳細講解有關如何解決C++結構體內(nèi)存對齊計算問題,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

編譯環(huán)境:vs2015

對齊原則:

      原則1:數(shù)據(jù)成員對齊規(guī)則:結構(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第一個數(shù)據(jù)成員放在offset為0的地方,以后每個數(shù)據(jù)成員的對齊按照#pragma pack指定的數(shù)值和這個數(shù)據(jù)成員自身長度中,比較小的那個進行。

      原則2:結構(或聯(lián)合)的整體對齊規(guī)則:在數(shù)據(jù)成員完成各自對齊之后,結構(或聯(lián)合)本身也要進行對齊,對齊將按照#pragma pack指定的數(shù)值和結構(或聯(lián)合)最大數(shù)據(jù)成員長度中,比較小的那個進行。

      原則3:結構體作為成員:如果一個結構里有某些結構體成員,則結構體成員要從其內(nèi)部最大元素大小的整數(shù)倍地址開始存儲。

默認對齊值:

Linux 默認#pragma pack(4)

window 默認#pragma pack(8)

注:可以通過預編譯命令#pragma pack(n) ,n=1,2,4,8,16來改變這一系數(shù),其中的n就是指定的“對齊系數(shù)”。

例一:一字節(jié)對齊

第一步: 成員數(shù)據(jù)對齊

#pragma pack(1)
struct AA {
 int a; //長度4 < 1 按1對齊;偏移量為0;存放位置區(qū)間[0,3]
 char b; //長度1 = 1 按1對齊;偏移量為4;存放位置區(qū)間[4]
 short c; //長度2 > 1 按1對齊;偏移量為5;存放位置區(qū)間[5,6]
 char d; //長度1 = 1 按1對齊;偏移量為6;存放位置區(qū)間[7]
 //整體存放在[0~7]位置區(qū)間中,共八個字節(jié)。
};
#pragma pack()

第二步: 整體對齊

整體對齊系數(shù) = min((max(int,short,char), 1) = 1,所以不需要再進行整體對齊。整體大小就為8。

圖示如下:

如何解決C++結構體內(nèi)存對齊計算問題

例二:二字節(jié)對齊

第一步: 成員數(shù)據(jù)對齊

#pragma pack(2)
struct AA {
 int a; //長度4 > 2 按2對齊;偏移量為0;存放位置區(qū)間[0,3]
 char b; //長度1 < 2 按1對齊;偏移量為4;存放位置區(qū)間[4]
 short c; //長度2 = 2 按2對齊;偏移量要提升到2的倍數(shù)6;存放位置區(qū)間[6,7]
 char d; //長度1 < 2 按1對齊;偏移量為7;存放位置區(qū)間[8];共九個字節(jié)
};
#pragma pack()

第二步: 整體對齊

整體對齊系數(shù) = min((max(int,short,char), 2) = 2,將9提升到2的倍數(shù),則為10.所以最終結果為10個字節(jié)。

圖示如下:(X為補齊部分)

如何解決C++結構體內(nèi)存對齊計算問題

例三:四字節(jié)對齊

第一步: 成員數(shù)據(jù)對齊

#pragma pack(4)
struct AA {
 int a; //長度4 = 4 按4對齊;偏移量為0;存放位置區(qū)間[0,3]
 char b; //長度1 < 4 按1對齊;偏移量為4;存放位置區(qū)間[4]
 short c; //長度2 < 4 按2對齊;偏移量要提升到2的倍數(shù)6;存放位置區(qū)間[6,7]
 char d; //長度1 < 4 按1對齊;偏移量為7;存放位置區(qū)間[8];總大小為9
};
#pragma pack()

第二步: 整體對齊

整體對齊系數(shù) = min((max(int,short,char), 4) = 4,將9提升到4的倍數(shù),則為12.所以最終結果為12個字節(jié)。

圖示如下:(X為補齊部分)

如何解決C++結構體內(nèi)存對齊計算問題

例三:八字節(jié)對齊

第一步: 成員數(shù)據(jù)對齊

#pragma pack(8)
struct AA {
 int a; //長度4 < 8 按4對齊;偏移量為0;存放位置區(qū)間[0,3]
 char b; //長度1 < 8 按1對齊;偏移量為4;存放位置區(qū)間[4]
 short c; //長度2 < 8 按2對齊;偏移量要提升到2的倍數(shù)6;存放位置區(qū)間[6,7]
 char d; //長度1 < 8 按1對齊;偏移量為7;存放位置區(qū)間[8],總大小為9
};
#pragma pack()

第二步: 整體對齊

整體對齊系數(shù) = min((max(int,short,char), 8) = 4,將9提升到4的倍數(shù),則為12.所以最終結果為12個字節(jié)。圖示如上。

注:可以通過stddef.h庫中的offsetof宏來查看對應結構體元素的偏移量。

例四:結構體中包含結構體的運算

整體計算過程如下

struct EE
{
 int a; //長度4 < 8 按4對齊;偏移量為0;存放位置區(qū)間[0,3]
 char b; //長度1 < 8 按1對齊;偏移量為4;存放位置區(qū)間[4]
 short c; //長度2 < 8 按2對齊;偏移量由5提升到6;存放位置區(qū)間[6,7]
 //結構體內(nèi)部最大元素為int,由于偏移量為8剛好是4的整數(shù)倍,所以從8開始存放接下來的struct FF
 struct FF
 {
 int a1; //長度4 < 8 按4對齊;偏移量為8;存放位置區(qū)間[8,11]
 char b1; //長度1 < 8 按1對齊;偏移量為12;存放位置區(qū)間[12]
 short c1; //長度2 < 8 按2對齊;偏移量為13,提升到2的倍數(shù)14;存放位置區(qū)間[14,15]
 char d1; //長度1 < 8 按1對齊;偏移量為16;存放位置區(qū)間[16]
 };
 //整體對齊系數(shù) = min((max(int,short,char), 8) = 4,將內(nèi)存大小由17補齊到4的整數(shù)倍20
 char d;  //長度1 < 8 按1對齊;偏移量為21;存放位置區(qū)間[21]
 //整體對齊系數(shù) = min((max(int,short,char), 8) = 4,將內(nèi)存大小由21補齊到4的整數(shù)倍24
};

圖示如下:

如何解決C++結構體內(nèi)存對齊計算問題

例五:再來一個嵌套結構體的計算

整體計算過程如下

struct B {
 char e[2]; //長度1 < 8 按2對齊;偏移量為0;存放位置區(qū)間[0,1]
 short h; //長度2 < 8 按2對齊;偏移量為2;存放位置區(qū)間[2,3]
 //結構體內(nèi)部最大元素為double,偏移量為4,提升到8,所以從8開始存放接下來的struct A
 struct A {
 int a; //長度4 < 8 按4對齊;偏移量為8;存放位置區(qū)間[8,11]
 double b; //長度8 = 8 按8對齊;偏移量為12,提升到16;存放位置區(qū)間16,23]
 float c; //長度4 < 8,按4對齊;偏移量為24,存放位置區(qū)間[24,27]
 };
 //整體對齊系數(shù) = min((max(int,double,float), 8) = 8,將內(nèi)存大小由28補齊到8的整數(shù)倍32
};

圖示如下:

如何解決C++結構體內(nèi)存對齊計算問題

小結:當#pragma pack的n值等于或超過所有數(shù)據(jù)成員長度的時候,這個n值的大小將不產(chǎn)生任何效果。

關于如何解決C++結構體內(nèi)存對齊計算問題就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

c++
AI