1. 程式人生 > >pragma 預處理指令

pragma 預處理指令

pragma 預編譯指令

progma指令是一條C/C++的預編譯指令,旨在為配置編譯選項,或者自定義編譯過程。每個編譯程式可以用#pragma指令啟用或終止該編譯程式支援的一些編譯功能。

目錄

文章目錄

#pragma message


 #pragma  message("訊息文字")  
  • 當編譯器遇到這條指令時就在編譯輸出視窗中將訊息文字打印出來,當我們在程式中定義了許多巨集來控制原始碼版本的時候,我們自己有可能都會忘記有沒有正確的設定這些巨集,此時我們可以用這條指令在編譯的時候就進行檢查。假設我們希望判斷自己有沒有在原始碼的什麼地方定義了_X86 這個巨集,可以用下面的方法:
#ifdef  _X86  
#pragma  message("_X86  macro  activated!")  
#endif  
  • 我們定義了_X86這個巨集以後,應用程式在編譯時就會在編譯輸出窗口裡顯示"_86 macro activated!"。我們就不會因為不記得自己定義的一些特定的巨集而抓耳撓腮了。

#pragma code_seg


 #pragma  code_seg( ["section-name" [, "section-class"] ] )  
  • 它能夠設定程式中函式程式碼存放的程式碼段,當我們開發驅動程式的時候就會使用到它。

#pragma data_seg

  • #pragma data_seg建立一個新的資料段並定義共享資料,其具體格式為:
#pragma data_seg("shareddata")
2 HWND sharedwnd = NULL;//共享資料
3 #pragma data_seg()
  • #pragma data_seg()一般用於DLL中。也就是說,在DLL中定義一個共享的有名字的資料段。最關鍵的是:這個資料段中的全域性變數可以被多個程序共享,否則多個程序之間無法共享DLL中的全域性變數。
  • 共享資料必須初始化,否則微軟編譯器會把沒有初始化的資料放到.BSS段中,從而導致多個程序之間的共享行為失敗。例如,
   #pragma data_seg("MyData")
 2 int g_Value;//未初始化的變數
 3 #pragma data_seg()
 4 //DLL提供兩個介面函式:
 5 int GetValue()
 6 {
 7     return g_Value;
 8 }
 9 void SetValue(int n)
10 {
11     g_Value=n;
12 }
  • 然後啟動兩個程序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,這就實現了跨程序之間的資料通訊。

#pragma hdrstop


  • 表示預編譯標頭檔案到此為止,後面的標頭檔案不進行預編譯。BCB可以預編譯標頭檔案以加快連結的速度,但如果所有標頭檔案都進行預編譯又可能佔太多磁碟空間,所以使用這個選項排除一些標頭檔案。
  • 有時單元之間有依賴關係,比如單元A依賴單元B,所以單元B要先於單元A編譯。
    你可以用#pragma startup指定編譯優先順序,如果使用了#pragma package(smart_init),BCB 就會根據優先順序的大小先後編譯。

#pragma resource


  • 表示把*.dfm檔案中的資源加入工程。*.dfm中包括窗體外觀的定義。

#pragma warning

#pragma  warning( disable: 4507 34; once: 4385; error: 164 )
  • 等價於:
    #pragma warning( disable: 4507 34 ) // 不顯示4507和34號警告資訊
    #pragma warning( once: 4385 ) // 4385號警告資訊僅報告一次
    #pragma warning( error: 164 ) // 把164號警告資訊作為一個錯誤。

#pragma comment


  • 該指令將一個註釋記錄放入一個物件檔案或可執行檔案中。
  • 常用的lib關鍵字,可以幫我們連入一個庫檔案。如:
#pragma  comment(lib, "comctl32.lib")
  • 和在工程設定裡寫上鍊入comctl32.lib的效果一樣,不過這種方法寫的 程式別人在使用你的程式碼的時候就不用再設定工程 settings 了。
  • 其他指令

1、compiler:
放置編譯器的版本或者名字到一個物件檔案,該選項是被linker忽略的。
2、exestr:
在以後的版本將被取消。

#pragma loop_opt


  • 開啟或關閉對迴圈優化功能
#pragma  loop_opt(on)     //  啟用  
#pragma  loop_opt(off)    //  終止 

#pragma pack


  • 記憶體對齊問題

  • 許多實際的計算機系統對基本型別資料在記憶體中存放的位置有限制,它們會要求這些資料的首地址的值是某個數k(通常它為4或8)的倍數,這就是所謂的記憶體對齊,而這個k則被稱為該資料型別的對齊模數(alignment modulus)。

  • Win32平臺下的微軟C編譯器(cl.exe for 80x86)在預設情況下采用如下的對齊規則: 任何基本資料型別T的對齊模數就是T的大小,即sizeof(T)。比如對於double型別(8位元組),
    就要求該型別資料的地址總是8的倍數,而char型別資料(1位元組)則可以從任何一個地址開始。

    Linux下的GCC奉行的是另外一套規則(在資料中查得,並未驗證,如錯誤請指正): 任何2位元組大小(包括單位元組嗎?)的資料型別(比如short)的對齊模數是2,而其它所有超過2位元組的資料型別(比如long,double)都以4為對齊模數。

    ANSI C規定一種結構型別的大小是它所有欄位的大小以及欄位之間或欄位尾部的填充區大小之和。填充區就是為了使結構體欄位滿足記憶體對齊要求而額外分配給結構體的空間。那麼結構體本身有什麼對齊要求嗎?有的,ANSI C標準規定結構體型別的對齊要求不能比它所有欄位中要求最嚴格的那個寬鬆,可以更嚴格。

#pragma once


  • 只要在標頭檔案的最開始加入這條指令就能夠保證標頭檔案被編譯一次,這條指令實際上在VC6中就已經有了,
    但是考慮到相容性並沒有太多的使用它。

#pragma hdrstop


  • 表示預編譯標頭檔案到此為止,後面的標頭檔案不進行預編譯。BCB可以預編譯標頭檔案以加快連結的速度,
    但如果所有標頭檔案都進行預編譯又可能佔太多磁碟空間,所以使用這個選項排除一些標頭檔案。

#pragma disable


  • 在函式前宣告,只對一個函式有效。該函式呼叫過程中將不可被中斷。一般在C51中使用較多。

#pragma region

  • #pragma regionVisual C++中特有的預處理指令。它可以讓你摺疊特定的程式碼塊,從而使介面更加清潔,便於編輯其他程式碼。摺疊後的程式碼塊不會影響編譯。你也可以隨時展開程式碼塊以進行編輯等操作。如下格式
#pragma region name
#pragma endregion comment

舉個例子

#pragma region Variables
3 HWND hWnd;
5 const size_t Max_Length = 20;
7 //other variables
9 #pragma endregion This region contains global variables.

參考部落格:
https://blog.csdn.net/qq_35624156/article/details/79864947
https://www.cnblogs.com/fnlingnzb-learner/p/5854494.html