天天看點

C++程式設計語言對記憶體的操作指南

C++程式設計語言對記憶體的操作是一個非常複雜的應用步驟,我們在學習的過程中,需要不斷的從實踐程式設計中去總結這方面的應用經驗,以幫助我們了解。在這裡我們就先來介紹一下C++記憶體對齊的相關方法。

  一、為什麼會有C++記憶體對齊

  以下内容節選自《Intel Architecture 32 Manual》。

  為了提高程式的性能,資料結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了通路未對齊的記憶體,處理器需要作兩次記憶體通路;然而,對齊的記憶體通路僅需要一次通路。

  一個字或雙字操作數跨越了4位元組邊界,或者一個四字操作數跨越了8位元組邊界,被認為是未對齊的,進而需要兩次總線周期來通路記憶體。一個字起始位址是奇數但卻沒有跨越字邊界被認為是對齊的,能夠在一個總線周期中被通路。

  二、C++記憶體對齊規則

  每個特定平台上的編譯器都有自己的預設“對齊系數”(也叫對齊模數)。程式員可以通過預編譯指令#pragma pack(n),n=1,2,4,8,16來改變這一系數,其中的n就是你要指定的“對齊系數”。

  對齊規則:

  1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第一個資料成員放在offset為0的地方,以後每個資料成員的對齊按照 #pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。

  2、結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊将按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。

  3、結合1、2推斷:當#pragma pack的n值等于或超過所有資料成員長度的時候,這個n值的大小将不産生任何效果。

  4.各成員變量存放的起始位址相對于結構的起始位址的偏移量必須為該變量的類型所占用的位元組數的倍數。

  5.各成員變量在存放的時候根據在結構中出現的順序依次申請空間,同時按照上面的對齊方式調整位置,空缺的位元組自動填充。

  6.同時為了確定結構的大小為結構的位元組邊界數(即該結構中占用最大空間的類型所占用的位元組數)的倍數,是以在為最後一個成員變量申請空間後,還會根據需要自動填充空缺的位元組。

  三、pragma pack 宏

  VC中提供了#pragma pack(n)來設定變量以n位元組對齊方式。n位元組對齊就是說變量存放的起始位址的偏移量有兩種情況:第一、如果n大于等于該變量所占用的位元組數,那麼偏移量必須滿足預設的對齊方式,第二、如果n小于該變量的類型所占用的位元組數,那麼偏移量為n的倍數,不用滿足預設的對齊方式。結構的總大小也有個限制條件,分下面兩種情況:如果n大于所有成員變量類型所占用的位元組數,那麼結構的總大小必須為占用空間最大的變量占用的空間數的倍數;否則必須為n的倍數。下面舉例說明其用法。

  #pragma pack(push) //儲存對齊狀态 #pragma pack(4)//設定為4位元組對齊 struct test { char m1; double m4; int m3; }; #pragma pack(pop)//恢複對齊狀态

  以上結構的大小為16,下面分析其存儲情況,首先為m1配置設定空間,其偏移量為0,滿足我們自己設定的對齊方式(4位元組對齊),m1占用1個位元組。接着開始為m4配置設定空間,這時其偏移量為1,需要補足3個位元組,這樣使偏移量滿足為n=4的倍數(因為sizeof(double)大于n),m4占用8個位元組。接着為m3配置設定空間,這時其偏移量為12,滿足為4的倍數,m3占用4個位元組。這時已經為所有成員變量配置設定了空間,共配置設定了16個位元組,滿足為n的倍數。如果把上面的#pragma pack(4)改為#pragma pack(16),那麼我們可以得到結構的大小為24。

  以上就是對C++記憶體對齊的相關介紹http://soft.chinabyte.com/database/317/11413817.shtml