日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

C++: 内存对齐

發(fā)布時(shí)間:2023/12/20 80 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++: 内存对齐 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是內(nèi)存對(duì)齊?
所謂的內(nèi)存對(duì)齊,就是為了讓內(nèi)存存取更加有效率而采取的一種優(yōu)化手段,對(duì)齊的結(jié)果是使得內(nèi)存中數(shù)據(jù)的首地址是CPU單次獲取數(shù)據(jù)大小的整數(shù)倍。
比如,CPU單次獲取數(shù)據(jù)的大小是4個(gè)字節(jié),對(duì)于 int x 而言,如果 x 的地址是0x00000000、0x00000004…等4的倍數(shù),就是內(nèi)存對(duì)齊。
此外,這里說的內(nèi)存對(duì)齊,一般就是針對(duì)結(jié)構(gòu)體來進(jìn)行探討的,所以這就可以理解在本文后面提到的對(duì)整體和成員有不同的對(duì)齊方式了。
為什么要內(nèi)存對(duì)齊?
1.硬件因素
經(jīng)過內(nèi)存對(duì)齊之后,CPU對(duì)內(nèi)存訪問的效率會(huì)大大提高。
舉個(gè)例子:
● 對(duì)于int變量 x 占用4個(gè)字節(jié)的內(nèi)存大小,假設(shè)它存放在 $ 0x00000003\sim0x00000006$ 的位置上,此時(shí) 0x00000003 不是4的整數(shù)倍。因此,對(duì)于每次只取4個(gè)字節(jié)的CPU而言,對(duì) x 的讀取就必須分兩次進(jìn)行,第一次讀取 $ 0x00000000\sim0x00000003$,第二次讀取 $ 0x00000004\sim0x00000007$,然后再進(jìn)行拼接處理,才能得到我們想要的數(shù)據(jù),可見這樣的效率會(huì)很低下。
● 倘若經(jīng)過對(duì)齊,即數(shù)據(jù)的首地址是CPU單次獲取數(shù)據(jù)大小的整數(shù)倍,假設(shè) x 存放在 $ 0x00000004\sim0x00000007$ 的位置,那么CPU只需要訪問一次內(nèi)存就可以讀取出 x 的值了。
2.可移植性
不是所有的硬件平臺(tái)都能訪問任意地址上的任意數(shù)據(jù)的,例如有些平臺(tái)上CPU在內(nèi)存非對(duì)齊的情況下執(zhí)行二進(jìn)制代碼會(huì)崩潰。為了代碼的可移植性,進(jìn)行內(nèi)存對(duì)齊是很有必要的。
如何進(jìn)行內(nèi)存對(duì)齊?
對(duì)齊方式
方式一: 編譯器提供了一種手動(dòng)指定對(duì)齊值的方式,只要在代碼前添加關(guān)鍵字 #pragma pack(n) 即可,其中 n 是手動(dòng)指定的內(nèi)存對(duì)齊的字節(jié)數(shù)。比如 #pragma pack(4)表示以4個(gè)字節(jié)進(jìn)行對(duì)齊。
方式二: 倘若沒有手動(dòng)設(shè)置對(duì)齊值,或者手動(dòng)設(shè)置的對(duì)齊值 n 大于成員變量中最大的類型的字節(jié)數(shù)(注意這一點(diǎn)!),編譯器則會(huì)默認(rèn)將成員變量中最大的類型的字節(jié)數(shù)設(shè)置為對(duì)齊值(假設(shè)為 m)。
對(duì)齊規(guī)則
● 成員對(duì)齊: ① 第一個(gè)成員的首地址為0
? ② 假設(shè)某成員的類型所占字節(jié)數(shù)為 k,則該成員的首地址為 min(n,k) 的整數(shù)倍。
● 整體對(duì)齊: 結(jié)構(gòu)體總的大小,應(yīng)該為 min(n,m) 的整數(shù)倍,如果不夠就在后面填補(bǔ)占位。
補(bǔ)充:如果不能理解上面說的 min(n,k)和 min(n,m),可以看下面的解釋:
● 對(duì)于min(n,k) 的理解:若手動(dòng)設(shè)置了對(duì)齊值 n,且 n<=k,那么首地址就是 n 的倍數(shù),也就是上面的對(duì)齊方式一;若 k<n,根據(jù)對(duì)齊方式二可知,編譯器不會(huì)將 n 作為對(duì)齊值,而是會(huì)選擇成員中最大類型的字節(jié)數(shù)(即 m)作為對(duì)齊值,由于 m>=k,則該值必然也是 k 的整數(shù)倍,因此 min(n,k) 就可以理解啦。
● 對(duì)于min(n,m) 的理解:根據(jù)對(duì)齊方式一和二,其實(shí)系統(tǒng)的對(duì)齊值就是n和m中最小的那個(gè)。當(dāng)然,整體對(duì)齊的意思是整個(gè)結(jié)構(gòu)體的總大小要對(duì)齊,不夠就填補(bǔ)占位。比如,假設(shè)對(duì)齊值為8,結(jié)構(gòu)體各個(gè)成員對(duì)齊之后的大小為12,由于12不是8的整數(shù)倍,所以編譯器會(huì)繼續(xù)填補(bǔ)4個(gè)空位,最終結(jié)構(gòu)體的總大小為16。
代碼解釋
對(duì)于方式一,手動(dòng)設(shè)置對(duì)齊值 #pragma pack(n),且n不大于成員變量的最大類型,此時(shí)編譯器的對(duì)齊值就是 n。
#include
#pragma pack(4) //對(duì)齊值為4using namespace std;struct MyStruct
{
char c;
double b;
int a;
};

int main() {
MyStruct data;
cout << sizeof(data.a) << endl; //結(jié)果為4
cout << sizeof(data.b) << endl; //結(jié)果為8
cout << sizeof(data.c) << endl; //結(jié)果為1,自動(dòng)填充3個(gè)字節(jié)
cout << sizeof(data) << endl; //結(jié)果為16,如果對(duì)齊值設(shè)置為8,這里結(jié)果就是24//system(“pause”);return 0;
}
對(duì)于方式二,先看不進(jìn)行手動(dòng)設(shè)置對(duì)齊值的情況,編譯器默認(rèn)將成員中最大類型的字節(jié)數(shù)作為對(duì)齊值,即double的類型大小,為 8,具體看代碼:

#include<iostream>using namespace std;struct MyStruct { char c; double b; int a; };int main() { MyStruct data; //沒有手動(dòng)設(shè)置對(duì)齊值,編譯器默認(rèn)為最大類型字節(jié)數(shù),即8 cout << sizeof(data.a) << endl; //結(jié)果為4,自動(dòng)填充4個(gè)字節(jié) cout << sizeof(data.b) << endl; //結(jié)果為8 cout << sizeof(data.c) << endl; //結(jié)果為1,自動(dòng)填充7個(gè)字節(jié) cout << sizeof(data) << endl; //結(jié)果為24//system("pause");return 0; }

對(duì)于方式二,手動(dòng)設(shè)置對(duì)齊值n,且n大于成員變量中的最大類型的字節(jié)數(shù)m,則編譯器采用m作為對(duì)齊值。

#include<iostream> #pragma pack(16) //設(shè)置對(duì)齊值為16,實(shí)際對(duì)齊值為sizeof(double)=8using namespace std;struct MyStruct { int a; double b; char c; };int main() { MyStruct data; cout << sizeof(data.a) << endl; //結(jié)果為4,自動(dòng)填充4個(gè)字節(jié) cout << sizeof(data.b) << endl; //結(jié)果為8 cout << sizeof(data.c) << endl; //結(jié)果為1,自動(dòng)填充7個(gè)字節(jié) cout << sizeof(data) << endl; //結(jié)果為24//system("pause");return 0; }

總結(jié)
用兩句話來總結(jié)一下內(nèi)存的對(duì)齊方式:
① 若沒有手動(dòng)設(shè)置對(duì)齊值,則編譯器默認(rèn)使用成員變量中最大的類型的字節(jié)數(shù)作為對(duì)齊值;
② 若手動(dòng)設(shè)置了對(duì)齊值,則編譯器會(huì)在默認(rèn)對(duì)齊值和手動(dòng)設(shè)置的對(duì)齊值之間選擇最小的那個(gè)作為最終對(duì)齊值。

總結(jié)

以上是生活随笔為你收集整理的C++: 内存对齐的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。