#pragma 預編譯指令的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。#pragma指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機或操作系統專有的特征。
其使用的格式一般為: #pragma Para。其中Para 為參數,常見的參數如下:
(1)Message參數
Message參數編譯信息輸出窗口中輸出相應地信息,使用方法如下:
#pragma message("消息文本")
使用示例,假如在程序中我們定義了很多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正確的設置這些宏,此時我們可以用這條指令在編譯的時候就進行檢查。假設我們希望判斷自己有沒有在源代碼的什么地方定義了_X86這個宏可以用下面的方法:
#ifdef _X86 #pragma message("_X86 macro activated!") #endif
(2)code_seg參數
code_seg參數可以設置程序中函數代碼存放的代碼段,使用方式如下:
#pragma code_seg(["section-name"[,"section-class"]])
(3)#program once 參數
其作用是在在頭文件的最開始加入這條指令,以保證頭文件被編譯一次。但#program once是編譯器相關的,就是說在這個編譯系統上能用,但在其他的編譯系統上就不一定能用,所以其可移植性較差。一般如果強調程序跨平台,還是選擇使用“#ifndef, #define, #endif”比較好。
(4)#program hdrstop
#program hdrstop表示預編譯頭文件到此為止,后面的頭文件不進行編譯。
(5)#program resource
#program resource “*.dfm”表示把*.dfm文件中的資源添加到工程。
(6)#program comment
#program comment將一個注釋記錄放入一個對象文件或可執行文件。
(7)#program data_seg
#program data_seg用來建立一個新的數據段並定義共享數據。如下:
#pragma data_seg("shareddata") HWNDsharedwnd=NULL;//共享數據 #pragma data_seg()
說明:a. #pragma data_seg()一般用於DLL中。也就是說,在DLL中定義一個共享的有名字的數據段。最關鍵的是:這個數據段中的全局變量可以被多個進程共享,否則多個進程之間無法共享DLL中的全局變量。
b. 共享數據必須初始化,否則微軟編譯器會把沒有初始化的數據放到.BSS段中,從而導致多個進程之間的共享行為失敗。例如:
#pragma data_seg("MyData") intg_Value; //Note that the global is not initialized. #pragma data_seg() //DLL提供兩個接口函數: int GetValue() { return g_Value; } void SetValue(int n) { g_Value=n; }
解釋:啟動兩個進程A和B,A和B都調用了這個DLL,假如A調用了SetValue(5); B接着調用int m = GetValue(); 那么m的值不一定是5,而是一個未定義的值。因為DLL中的全局數據對於每一個調用它的進程而言,是私有的,不能共享的。假如你對g_Value進行了初始化,那么g_Value就一定會被放進MyData段中。換句話說,如果A調用了SetValue(5); B接着調用int m = GetValue(); 那么m的值就一定是5,這就實現了跨進程之間的數據通信。
(8)#program region
#program region用於折疊特定的代碼段,示例如下:
#pragma region Variables HWND hWnd; const size_t Max_Length = 20; //other variables #pragma endregion This region contains global variables.
應用實例:在網絡協議編程中,經常會處理不同協議的數據報文。一種方法是通過指針偏移的方法來得到各種信息,但這樣做不僅編程復雜,而且一旦協議有變化,程序修改起來也比較麻煩。在了解了編譯器對結構空間的分配原則之后,我們完全可以利用這一特性定義自己的協議結構,通過訪問結構的成員來獲取各種信息。這樣做,不僅簡化了編程,而且即使協議發生變化,我們也只需修改協議結構的定義即可,其它程序無需修改,省時省力。下面以TCP協議首部為例,說明如何定義協議結構。
協議的定義結構如下:
#pragma pack(1) //按照1字節方式進行對齊 struct TCPHEADER { shortSrcPort; //16位源端口號 shortDstPort; //16位目的端口號 intSerialNo; //32位序列號 intAckNo; //32位確認號 unsignedcharHaderLen:4; //4位首部長度 unsignedcharReserved1:4; //保留16位中的4位 unsignedcharReserved2:2; //保留16位中的2位 unsignedcharURG:1; unsignedcharACK:1; unsignedcharPSH:1; unsignedcharRST:1; unsignedcharSYN:1; unsignedcharFIN:1; shortWindowSize; //16位窗口大小 shortTcpChkSum; //16位TCP檢驗和 shortUrgentPointer; //16位緊急指針 }; #pragm apop() //取消1字節對齊方式
#pragma pack規定的對齊長度,實際使用的規則是: 結構,聯合,或者類的數據成員,第一個放在偏移為0的地方,以后每個數據成員的對齊,按照#pragma pack指定的數值和這個數據成員自身長度中,比較小的那個進行。 但是,當#pragma pack的值等於或超過最長數據成員的長度的時候,這個值的大小將不產生任何效果。 而結構整體的對齊,則按照結構體中最大的數據成員進行。