在閱讀代碼特別是C語法代碼的過程中,其實經(jīng)常會遇到#pragma pack(n),#pragma pack(),#pragma pack(pack,n),#pragma pack(pop,n)等,其中n是可以省略的。
并且這些語句一般出現(xiàn)在結(jié)構(gòu)體前面。我們一般都知道該語句是用來進行內(nèi)存對齊的,但是總結(jié)得不是特別清晰。
我在查閱博客的過程中,找到了一個總結(jié)得比較好的帖子,然后補充一點我自己的情況。
以下是原博客內(nèi)容(#pragma pack 指令詳解!):
#pragma pack這個指令和他涉及的c/c++內(nèi)存對齊機制可能是技術(shù)開發(fā)類筆試面試被問道的最頻繁的問題之一了
,可惜筆者在實際生活中發(fā)現(xiàn)大量的工程人員乃至面試官自身對于這個預(yù)處理指令都是一知半解,所以今天在簡
書為大家詳細講解一下這個指令。
1.#pragma簡述:
在所有的預(yù)處理指令中,#Pragma 指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動作。#pragma指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機器或操作系統(tǒng)專有的,且對于每個編譯器都是不同的。 今天為大家說的就是其中的#pragma pack指令。
2.#pragma pack的作用:
這個其實點進這個帖子的人都懂,#pragma pack 的主要作用就是改變編譯器的內(nèi)存對齊方式,這個指令在網(wǎng)絡(luò)報文的處理中有著重要的作用,#pragma pack(n)是他最基本的用法,其作用是改變編譯器的對齊方式, 不使用這條指令的情況下,編譯器默認采取#pragma pack(8)也就是8字節(jié)的默認對齊方式,n值可以?。?code>1, 2, 4, 8, 16) 中任意一值。
3.#pragma pack詳細介紹:
想必大家也看煩了,那么下面我就開始為大家介紹#pragma pack的詳細用法:
3.1 #pragma pack(show):
#pragma pack(show)顯示當前內(nèi)存對齊的字節(jié)數(shù)。也就是packing aligment。
我們常說編譯器默認8字節(jié)對齊我們怎么知道的呢?
如下圖所示:


在程序中#pragma pack(show)會在編譯階段提出一個警告,說明當前對齊字節(jié)數(shù)。
3.2 #pragma pack(push [, identifier] [, n])
單純使用#pragma pack(push)會將當前的對齊字節(jié)數(shù)壓入棧頂,并設(shè)置這個值為新的對齊字節(jié)數(shù), 就是說不會改變這個值。
而使用#pragma pack(push, n) 會將當前的對齊字節(jié)數(shù)壓入棧頂,并設(shè)置n為新的對齊字節(jié)數(shù)。
再就是這個#pragma pack(push, identifier [, n])會在上面的操作基礎(chǔ)上為這個對齊字節(jié)數(shù)附上一個標識符, 這里注意這個標識符只能以($、_、字母)開始, 標識符中可以有($、_、字母、數(shù)字),并且標識符不能是關(guān)鍵字(push, pop可以作為標識符)。這個標識符的作用我會在pop中詳細介紹。
push的使用:


3.3 #pragma pack(pop [, identifier] [, n])
同樣單純使用#pragma pack(pop)會彈出棧頂對齊字節(jié)數(shù),并設(shè)置其為新的內(nèi)存對齊字節(jié)數(shù)。


使用#pragma pack(pop, n)情況就不同了, 他會彈出棧頂并直接丟棄,設(shè)置n為其新的內(nèi)存對齊字節(jié)數(shù)。


#pragma pack(pop, identifier [, n])較為復(fù)雜,編譯器執(zhí)行這條執(zhí)行時會從棧頂向下順序查找匹配的identifier,找到identifier相同的這個數(shù)之后將從棧頂?shù)?code>identifier,包括找到identifier全部pop彈出, 若沒有找到則不進行任何操作。


由于前面提到的push和pop也可以作為關(guān)鍵字所以可以設(shè)計出很有戲劇效果的預(yù)處理頭:


#pragma pack一系列的預(yù)處理指令在網(wǎng)絡(luò)報文構(gòu)造中有著重要的應(yīng)用,是編譯器處理內(nèi)存的重要指令,同時我也希望各位面試官注意自身知識體系,不要再自己一知半解的情況下亂問問題,我會在下次寫一篇關(guān)于C++內(nèi)存對齊的詳細介紹敬請期待!
以上是原博客內(nèi)容
下面是我遇到的一點情況(見注釋):
#pragma pack(show)//默認內(nèi)存對其按照8個字節(jié),==8
#pragma pack(4)//將8個字節(jié)對齊改成了4個字節(jié)
#pragma pack(show)//==4
typedef struct
{
uint32_t iDeviceType; // see above defines
char szPath[512]; // device path to use in FZ_Open
char szShortName[32]; // a more user friendly name
char szSerial[16]; // device serial number
uint32_t iReserved[64];
} FZ_DEVICE_INFO;
#pragma pack(show)//==4,沒有發(fā)生改變
#pragma pack()//將內(nèi)存對齊設(shè)置變成默認的8個字節(jié)
#pragma pack(show)//==8