天天看點

關于#pragma once

在所有的預處理指令中,#pragma指令可能是最複雜的了,它的作用是設定編譯器的狀态或者是訓示編譯器完成一些特定的動作。#pragma指令對每個 編譯器給出了一個方法,在保持與C和C++語言完全相容的情況下,給出主機或作業系統專有的特征。依據定義,編譯訓示是機器或作業系統專有的,且對于每個 編譯器都是不同的。其格式一般為:#pragma para,其中para為參數,下面來看一些常用的參數。

(Each   implementation   of   C   and   C++   supports   some   features   unique   to   its   host   machine   or   operating   system.   Some   programs,   for   instance,   need   to   exercise   precise   control   over   the   memory   areas   where   data   is   placed   or   to   control   the   way   certain   functions   receive   parameters.   The   #pragma   directives   offer   a   way   for   each   compiler   to   offer   machine-   and   operating-system-specific   features   while   retaining   overall   compatibility   with   the   C   and   C++   languages.   Pragmas   are   machine-   or   operating-system-specific   by   definition,   and   are   usually   different   for   every   compiler. )

(1)message參數。Message參數是我最喜歡的一個參數,它能夠在編譯資訊輸出視窗中輸出相應的資訊,這對于源代碼資訊的控制是非常重要的。其使用方法為:

#pragma message(“消息文本”),當編譯器遇到這條指令時就在編譯輸出視窗中将消

息文本列印出來。

當我們在程式中定義了許多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正确的設定這些宏,此時我們可以用這條指令在編譯的時候就進行檢查。假設我們希望判斷自己有沒有在源代碼的什麼地方定義了_X86這個宏可以用下面的方法:    

#ifdef   _X86    

#pragma   message(“_X86   macro   activated!”)    

#endif    

當我們定義了_X86這個宏以後,應用程式在編譯時就會在編譯輸出視窗裡顯示

“_X86   macro activated!”。我們就不會因為不記得自己定義的一些特定的宏而抓耳

撓腮了。    

(2)另一個使用得比較多的pragma參數是code_seg。格式如:    

#pragma   code_seg(   ["section-name"[,"section-class"]   ]   )    

它能夠設定程式中函數代碼存放的代碼段,當我們開發驅動程式的時候就會使用到它。    

(3)#pragma once (比較常用)。隻要在頭檔案的最開始加入這條指令就能夠保證

頭檔案被編譯一次,這條指令實際上在VC6中就已經有了,但是考慮到相容性并沒有太多的使用它。    

(4)#pragma hdrstop表示預編譯頭檔案到此為止,後面的頭檔案不進行預編譯。BCB

可以預編譯頭檔案以加快連結的速度,但如果所有頭檔案都進行預編譯又可能占太多磁盤空間,是以使用這個選項排除一些頭檔案。有時單元之間有依賴關系,比如單元A依賴單元B,是以單元B要先于單元A編譯。你可以用#pragma   startup指定編

譯優先級,如果使用了#pragma package(smart_init),BCB就會根據優先級的大小先

後編譯。    

(5)#pragma   resource   "*.dfm"表示把*.dfm檔案中的資源加入工程。*.dfm中包括窗

體外觀的定義。    

(6)#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   warning   也支援如下格式:    

#pragma   warning(   push   [   ,n   ]   )    

#pragma   warning(   pop   )    

這裡n代表一個警告等級(1---4)。    

#pragma   warning(   push   )儲存所有警告資訊的現有的警告狀态。    

#pragma   warning(   push,   n)儲存所有警告資訊的現有的警告狀态,并且全局警告    

等級設定為n。    

#pragma   warning(   pop   )向棧中彈出最後一個警告資訊,在入棧和出棧之間所作

的一切改動取消。例如:    

#pragma   warning(   push   )    

#pragma   warning(   disable   :   4705   )    

#pragma   warning(   disable   :   4706   )    

#pragma   warning(   disable   :   4707   )    

//.......    

#pragma   warning(   pop   )    

在這段代碼的最後,重新儲存所有的警告資訊(包括4705,4706和4707)。    

(7)#pragma   comment(...) 該指令将一個注釋記錄放入一個對象檔案或可執行

檔案中。常用的lib關鍵字,可以幫我們連入一個庫檔案。  

(8)#pragma   pack() 我們知道在VC中,對于想結構體Struct這樣的類型,VC采

用8位元組對齊的方式,如果我們不想使用8位元組對齊(在網絡變成中經常需要這樣),我們可以在結構體前面加上    

#pragma   pack(1)    

struct    

{    

......    

}    

#pragma   pack()

二.#if _MSC_VER > 1000    #pragma once    #endif  

(1)_MSC_VER。 Defines   the   compiler   version.   Defined   as   1200   for   Microsoft   Visual   C++   6.0.   Always   defined.   

(2)#if   _MSC_VER   > 1000的意思是指如果vc編譯器的版本大于1000則這個語句

被編譯!大概小于1000的版本不支援#pragma   once這個語句。

(3)#pragma   once 。Specifies   that   the   file,   in   which   the   pragma   resides,

will   be   included   (opened)   only   once   by   the   compiler   in   a   build.   A   common   use   for   this   pragma   is   the   following:  

//header.h  

#pragma   once  

//   Your   C   or   C++   code   would   follow:  

#pragma   once    加入頭檔案的第一行 訓示這個檔案在編譯時隻被編譯器檔案編譯

(打開)一次!一般用到.h中防止檔案被重複包括!  

三.#pragma once    與   #ifndef    #define   #endif  

(1)從定義上即可看出,pragmas指令是某種機器或者作業系統獨有的,并且不同編譯器也常常有别。#pragma once這個是編譯器相關指令,就是說在這個編譯系統

上能用,但是在其他編譯系統 不一定型,也就是說移植型差。不過現在基本上

已經是每個編譯器都有這個定義了。

#ifndef   #define #endif這個是語言支援指令,這是C/C++語言中的宏定義,通過

宏定義避免檔案多次編譯。是以在所有支援C++語言的編譯器上都是有效的。如果寫的程式要   跨平台,最好使用這種方式。

(2)#ifndef   #define #endif   #ifndef 還有其它作用,防止頭檔案重複引用隻是

其中一個應用而已。#pragma隻有微軟支援。

(3)#ifndef   #define #endif   他讀到#ifndef之後,如果已經定義過了,就會跳過

這一大片,一直到#endif為止。這将增加build時間,因為每次compiler都會打開這個檔案,然後搜尋全檔案一遍。而如果碰到了#pragma once,他就會立刻停止,

關閉打開的這個檔案。在某種程度上減少 了build時間。一般用法:   

#ifndef  

#define  

#pragma   once  

.....  

#endif  

四. #pragma   data_seg(".mdata").....#pragma data_seg()可以讓編譯器把兩者之間

的所有已初始化變量放入一個新的.mdata段中。應用之一是單應用程式。

有的時候我們可能想讓一個應用程式隻啟動一次,就像單件模式(singleton)一樣,實作的方法可能有多種,這裡說說用#pragma data_seg的實作,很是簡潔便利。

應用程式的入口檔案前面加上:

#pragma data_seg("flag_data")

int app_count = 0;

#pragma data_seg()

#pragma comment(linker,"/SECTION:flag_data,RWS")

然後程式啟動的地方加上

if(app_count>0) // 如果計數大于0,則退出應用程式。

{

//MessageBox(NULL, "已經啟動一個應用程式", "Warning", MB_OK);

//printf("no%d application", app_count);

return FALSE;

} app_count++;

總結:

1. #ifndef 由語言支援是以移植性好,#pragma 可以避免名字沖突

2. 調查一下<stdlib.h>和<iostream>等标準庫, 用得都是#ifndef, 我個人推薦這種方式.