#pragma pack這個指令和他涉及的c/c++內存對齊機制可能是技術開發類筆試面試被問道的最頻繁的問題之一了
,可惜筆者在實際生活中發現大量的工程人員乃至面試官自身對于這個預處理指令都是一知半解,所以今天在簡
書為大家詳細講解一下這個指令。
1.#pragma簡述:
在所有的預處理指令中,#Pragma
指令可能是最復雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。#pragma
指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機或操作系統專有的特征。依據定義,編譯指示是機器或操作系統專有的,且對于每個編譯器都是不同的。 今天為大家說的就是其中的#pragma pack
指令。
2.#pragma pack的作用:
這個其實點進這個帖子的人都懂,#pragma pack
的主要作用就是改變編譯器的內存對齊方式,這個指令在網絡報文的處理中有著重要的作用,#pragma pack(n)
是他最基本的用法,其作用是改變編譯器的對齊方式, 不使用這條指令的情況下,編譯器默認采取#pragma pack(8)
也就是8字節的默認對齊方式,n值可以取(1
, 2
, 4
, 8
, 16
) 中任意一值。
3.#pragma pack詳細介紹:
想必大家也看煩了,那么下面我就開始為大家介紹#pragma pack的詳細用法:
3.1 #pragma pack(show):
#pragma pack(show)
顯示當前內存對齊的字節數。也就是packing aligment
。
我們常說編譯器默認8字節對齊我們怎么知道的呢?
如下圖所示:
在程序中#pragma pack(show)會在編譯階段提出一個警告,說明當前對齊字節數。
3.2 #pragma pack(push [, identifier] [, n])
單純使用#pragma pack(push)
會將當前的對齊字節數壓入棧頂,并設置這個值為新的對齊字節數, 就是說不會改變這個值。
而使用#pragma pack(push, n)
會將當前的對齊字節數壓入棧頂,并設置n為新的對齊字節數。
再就是這個#pragma pack(push, identifier [, n])
會在上面的操作基礎上為這個對齊字節數附上一個標識符, 這里注意這個標識符只能以($
、_
、字母
)開始, 標識符中可以有($
、_
、字母
、數字
),并且標識符不能是關鍵字(push, pop可以作為標識符
)。這個標識符的作用我會在pop中詳細介紹。
push的使用:
3.3 #pragma pack(pop [, identifier] [, n])
同樣單純使用#pragma pack(pop)
會彈出棧頂對齊字節數,并設置其為新的內存對齊字節數。
使用
#pragma pack(pop, n)
情況就不同了, 他會彈出棧頂并直接丟棄,設置n
為其新的內存對齊字節數。
#pragma pack(pop, identifier [, n])
較為復雜,編譯器執行這條執行時會從棧頂向下順序查找匹配的identifier
,找到identifier
相同的這個數之后將從棧頂到identifier
,包括找到identifier
全部pop
彈出, 若沒有找到則不進行任何操作。
由于前面提到的
push
和pop
也可以作為關鍵字所以可以設計出很有戲劇效果的預處理頭:
#pragma pack
一系列的預處理指令在網絡報文構造中有著重要的應用,是編譯器處理內存的重要指令,同時我也希望各位面試官注意自身知識體系,不要再自己一知半解的情況下亂問問題,我會在下次寫一篇關于C++內存對齊的詳細介紹敬請期待!
簡書●null122轉載請注明出處