在所有的預(yù)處理指令中,#pragma指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動作。#pragma指令對每個 編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機器或操作系統(tǒng)專有的,且對于每個 編譯器都是不同的。其格式一般為:#pragma para,其中para為參數(shù),下面來看一些常用的參數(shù)。
(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參數(shù)。Message參數(shù)是我最喜歡的一個參數(shù),它能夠在編譯信息輸出窗口中輸出相應(yīng)的信息,這對于源代碼信息的控制是非常重要的。其使用方法為:
#pragma message(“消息文本”),當(dāng)編譯器遇到這條指令時就在編譯輸出窗口中將消
息文本打印出來。
當(dāng)我們在程序中定義了許多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正確的設(shè)置這些宏,此時我們可以用這條指令在編譯的時候就進(jìn)行檢查。假設(shè)我們希望判斷自己有沒有在源代碼的什么地方定義了_X86這個宏可以用下面的方法:
#ifdef _X86
#pragma message(“_X86 macro activated!”)
#endif
當(dāng)我們定義了_X86這個宏以后,應(yīng)用程序在編譯時就會在編譯輸出窗口里顯示
“_X86 macro activated!”。我們就不會因為不記得自己定義的一些特定的宏而抓耳
撓腮了。
(2)另一個使用得比較多的pragma參數(shù)是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開發(fā)驅(qū)動程序的時候就會使用到它。
(3)#pragma once (比較常用)。只要在頭文件的最開始加入這條指令就能夠保證
頭文件被編譯一次,這條指令實際上在VC6中就已經(jīng)有了,但是考慮到兼容性并沒有太多的使用它。
(4)#pragma hdrstop表示預(yù)編譯頭文件到此為止,后面的頭文件不進(jìn)行預(yù)編譯。BCB
可以預(yù)編譯頭文件以加快鏈接的速度,但如果所有頭文件都進(jìn)行預(yù)編譯又可能占太多磁盤空間,所以使用這個選項排除一些頭文件。有時單元之間有依賴關(guān)系,比如單元A依賴單元B,所以單元B要先于單元A編譯。你可以用#pragma startup指定編
譯優(yōu)先級,如果使用了#pragma package(smart_init),BCB就會根據(jù)優(yōu)先級的大小先
后編譯。
(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 )保存所有警告信息的現(xiàn)有的警告狀態(tài)。
#pragma warning( push, n)保存所有警告信息的現(xiàn)有的警告狀態(tài),并且全局警告
等級設(shè)定為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(...) 該指令將一個注釋記錄放入一個對象文件或可執(zhí)行
文件中。常用的lib關(guān)鍵字,可以幫我們連入一個庫文件。
(8)#pragma pack() 我們知道在VC中,對于想結(jié)構(gòu)體Struct這樣的類型,VC采
用8字節(jié)對齊的方式,如果我們不想使用8字節(jié)對齊(在網(wǎng)絡(luò)變成中經(jīng)常需要這樣),我們可以在結(jié)構(gòu)體前面加上
#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中防止文件被重復(fù)包括!
三.#pragma once 與 #ifndef #define #endif
(1)從定義上即可看出,pragmas指令是某種機器或者操作系統(tǒng)獨有的,并且不同編譯器也常常有別。#pragma once這個是編譯器相關(guān)指令,就是說在這個編譯系統(tǒng)
上能用,但是在其他編譯系統(tǒng) 不一定型,也就是說移植型差。不過現(xiàn)在基本上
已經(jīng)是每個編譯器都有這個定義了。
#ifndef #define #endif這個是語言支持指令,這是C/C++語言中的宏定義,通過
宏定義避免文件多次編譯。所以在所有支持C++語言的編譯器上都是有效的。如果寫的程序要 跨平臺,最好使用這種方式。
(2)#ifndef #define #endif #ifndef 還有其它作用,防止頭文件重復(fù)引用只是
其中一個應(yīng)用而已。#pragma只有微軟支持。
(3)#ifndef #define #endif 他讀到#ifndef之后,如果已經(jīng)定義過了,就會跳過
這一大片,一直到#endif為止。這將增加build時間,因為每次compiler都會打開這個文件,然后搜索全文件一遍。而如果碰到了#pragma once,他就會立刻停止,
關(guān)閉打開的這個文件。在某種程度上減少 了build時間。一般用法:
#ifndef
#define
#pragma once
.....
#endif
四. #pragma data_seg(".mdata").....#pragma data_seg()可以讓編譯器把兩者之間
的所有已初始化變量放入一個新的.mdata段中。應(yīng)用之一是單應(yīng)用程序。
有的時候我們可能想讓一個應(yīng)用程序只啟動一次,就像單件模式(singleton)一樣,實現(xiàn)的方法可能有多種,這里說說用#pragma data_seg的實現(xiàn),很是簡潔便利。
應(yīng)用程序的入口文件前面加上:
#pragma data_seg("flag_data")
int app_count = 0;
#pragma data_seg()
#pragma comment(linker,"/SECTION:flag_data,RWS")
然后程序啟動的地方加上
if(app_count>0) // 如果計數(shù)大于0,則退出應(yīng)用程序。
{
//MessageBox(NULL, "已經(jīng)啟動一個應(yīng)用程序", "Warning", MB_OK);
//printf("no%d application", app_count);
return FALSE;
} app_count++;
總結(jié):
1. #ifndef 由語言支持所以移植性好,#pragma 可以避免名字沖突
2. 調(diào)查一下<stdlib.h>和<iostream>等標(biāo)準(zhǔn)庫, 用得都是#ifndef, 我個人推薦這種方式.