#pragma comment和#pragma 预处理指令详解
??? 例如,#pragma?? comment(lib,"Ws2_32.lib")表示鏈接Ws2_32.lib這個(gè)庫。 和在工程設(shè)置里寫上鏈入Ws2_32.lib的效果一樣,不過這種方法寫的 程序別人在使用你的代碼的時(shí)候就不用再設(shè)置工程settings了。
#pragma comment( comment-type [,"commentstring"] )comment-type是一個(gè)預(yù)定義的標(biāo)識符,指定注釋的類型,應(yīng)該是compiler,exestr,lib,linker之一。 commentstring是一個(gè)提供為comment-type提供附加信息的字符串, Remarks: 1、compiler:放置編譯器的版本或者名字到一個(gè)對象文件,該選項(xiàng)是被linker忽略的。 2、exestr:在以后的版本將被取消。 3、lib:放置一個(gè)庫搜索記錄到對象文件中,這個(gè)類型應(yīng)該是和commentstring(指定你要Liner搜索的lib的名稱和路徑) 這個(gè)庫的名字放在Object文件的默認(rèn)庫搜索記錄的后面,linker搜索這個(gè)這個(gè)庫就像你在命令行輸入這個(gè)命令一樣。你可以 在一個(gè)源文件中設(shè)置多個(gè)庫記錄,它們在object文件中的順序和在源文件中的順序一樣。如果默認(rèn)庫和附加庫的次序是需要 區(qū)別的,使用Z編譯開關(guān)是防止默認(rèn)庫放到object模塊。 4、linker:指定一個(gè)連接選項(xiàng),這樣就不用在命令行輸入或者在開發(fā)環(huán)境中設(shè)置了。 只有下面的linker選項(xiàng)能被傳給Linker.
-
/DEFAULTLIB
-
/EXPORT
-
/INCLUDE
-
/MANIFESTDEPENDENCY
-
/MERGE
-
/SECTION
忽略所有默認(rèn)庫 (/NODEFAULTLIB) 選項(xiàng)重寫 /DEFAULTLIB:library。如果在兩者中指定了相同的 library 名稱,忽略庫 (/NODEFAULTLIB:library) 選項(xiàng)將重寫 /DEFAULTLIB:library。
(2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
使用該選項(xiàng),可以從程序?qū)С龊瘮?shù),以便其他程序可以調(diào)用該函數(shù)。也可以導(dǎo)出數(shù)據(jù)。通常在 DLL 中定義導(dǎo)出。entryname 是調(diào)用程序要使用的函數(shù)或數(shù)據(jù)項(xiàng)的名稱。ordinal 在導(dǎo)出表中指定范圍在 1 至 65,535 的索引;如果沒有指定 ordinal,則 LINK 將分配一個(gè)。NONAME 關(guān)鍵字只將函數(shù)導(dǎo)出為序號,沒有 entryname。
DATA 關(guān)鍵字指定導(dǎo)出項(xiàng)為數(shù)據(jù)項(xiàng)。客戶程序中的數(shù)據(jù)項(xiàng)必須用 extern __declspec(dllimport) 來聲明。
有三種導(dǎo)出定義的方法,按照建議的使用順序依次為:
源代碼中的 __declspec(dllexport)
.def 文件中的 EXPORTS 語句
LINK 命令中的 /EXPORT 規(guī)范
所有這三種方法可以用在同一個(gè)程序中。LINK 在生成包含導(dǎo)出的程序時(shí)還創(chuàng)建導(dǎo)入庫,除非生成中使用了 .exp 文件。
LINK 使用標(biāo)識符的修飾形式。編譯器在創(chuàng)建 .obj 文件時(shí)修飾標(biāo)識符。如果 entryname 以其未修飾的形式指定給鏈接器(與其在源代碼中一樣),則 LINK 將試圖匹配該名稱。如果無法找到唯一的匹配名稱,則 LINK 發(fā)出錯(cuò)誤信息。當(dāng)需要將標(biāo)識符指定給鏈接器時(shí),請使用 Dumpbin 工具獲取該標(biāo)識符的修飾名形式。
/INCLUDE 選項(xiàng)通知鏈接器將指定的符號添加到符號表。
若要指定多個(gè)符號,請?jiān)诜柮Q之間鍵入逗號 (,)、分號 (;) 或空格。在命令行上,對每個(gè)符號指定一次 /INCLUDE:symbol。
鏈接器通過將包含符號定義的對象添加到程序來解析 symbol。該功能對于添包含不會鏈接到程序的庫對象非常有用。用該選項(xiàng)指定符號將通過 /OPT:REF 重寫該符號的移除。
MSDN描述(http://msdn.microsoft.com/zh-cn/library/aa273890.aspx): Places a comment record into an object file or executable file. The comment-type is one of five predefined identifiers, described below, that specify the type of comment record. The optional commentstring is a string literal that provides additional information for some comment types. Because commentstring is a string literal, it obeys all the rules for string literals with respect to escape characters, embedded quotation marks ("), and concatenation.?
compiler?
Places the name and version number of the compiler in the object file. This comment record is ignored by the linker. If you supply a commentstring parameter for this record type, the compiler generates a warning.?
exestr?
Places commentstring in the object file. At link time, this string is placed in the executable file. The string is not loaded into memory when the executable file is loaded; however, it can be found with a program that finds printable strings in files. One use for this comment-record type is to embed a version number or similar information in an executable file.?
lib?
Places a library-search record in the object file. This comment type must be accompanied by a commentstring parameter containing the name (and possibly the path) of the library that you want the linker to search. Since the library name precedes the default library-search records in the object file, the linker searches for this library just as if you had named it on the command line. You can place multiple library-search records in the same source file; each record appears in the object file in the same order in which it is encountered in the source file.?
linker?
Places a linker option in the object file. You can use this comment-type to specify a linker option instead placing the option on the Link tab of the Project Settings dialog box. For example, you can specity the /include option to force the inclusion of a symbol:?
#pragma comment(linker, "/include:__mySymbol")?
user?
Places a general comment in the object file. The commentstring parameter contains the text of the comment. This comment record is ignored by the linker.?
The following pragma causes the linker to search for the EMAPI.LIB library while linking. The linker searches first in the current working directory and then in the path specified in the LIB environment variable.?
#pragma comment( lib, "emapi" )?
The following pragma causes the compiler to place the name and version number of the compiler in the object file:?
#pragma comment( compiler )?
Note For comments that take a commentstring parameter, you can use a macro in any place where you would use a string literal, provided that the macro expands to a string literal. You can also concatenate any combination of string literals and macros that expand to string literals. For example, the following statement is acceptable:?
#pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )
=================================================================================
#pragma 預(yù)處理指令詳解
(http://social.msdn.microsoft.com/Forums/zh-CN/visualcpluszhchs/thread/106caa63-24bb-41c5-816d-a56996df10b8/):
在所有的預(yù)處理指令中,#Pragma?? 指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或?
者是指示編譯器完成一些特定的動作。#pragma指令對每個(gè)編譯器給出了一個(gè)方法,在保持與?
C和C++語言完全兼容的情況下,給出主機(jī)或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機(jī)器?
或操作系統(tǒng)專有的,且對于每個(gè)編譯器都是不同的。?
其格式一般為:?? #Pragma?? Para?
其中Para 為參數(shù),下面來看一些常用的參數(shù)。?
(1)message 參數(shù)。?? Message?? 參數(shù)是我最喜歡的一個(gè)參數(shù),它能夠在編譯信息輸出窗?
口中輸出相應(yīng)的信息,這對于源代碼信息的控制是非常重要的。其使用方法為:?
#Pragma?? message(“消息文本”)?
當(dāng)編譯器遇到這條指令時(shí)就在編譯輸出窗口中將消息文本打印出來。?
當(dāng)我們在程序中定義了許多宏來控制源代碼版本的時(shí)候,我們自己有可能都會忘記有沒有正?
確的設(shè)置這些宏,此時(shí)我們可以用這條指令在編譯的時(shí)候就進(jìn)行檢查。假設(shè)我們希望判斷自?
己有沒有在源代碼的什么地方定義了_X86這個(gè)宏可以用下面的方法?
#ifdef?? _X86?
#Pragma?? message(“_X86?? macro?? activated!”)?
#endif?
當(dāng)我們定義了_X86這個(gè)宏以后,應(yīng)用程序在編譯時(shí)就會在編譯輸出窗口里顯示“_?
X86?? macro?? activated!”。我們就不會因?yàn)椴挥浀米约憾x的一些特定的宏而抓耳撓腮了?。?
(2)另一個(gè)使用得比較多的pragma參數(shù)是code_seg。格式如:?
#pragma?? code_seg(?? [\section-name\[,\section-class\]?? ]?? )?
它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開發(fā)驅(qū)動程序的時(shí)候就會使用到它。?
(3)#pragma?? once ?(比較常用)?
只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實(shí)際上在VC6?
中就已經(jīng)有了,但是考慮到兼容性并沒有太多的使用它。?
(4)#pragma?? hdrstop 表示預(yù)編譯頭文件到此為止,后面的頭文件不進(jìn)行預(yù)編譯。BCB可以預(yù)?
編譯頭文件以加快鏈接的速度,但如果所有頭文件都進(jìn)行預(yù)編譯又可能占太多磁盤空間,所?
以使用這個(gè)選項(xiàng)排除一些頭文件。?
有時(shí)單元之間有依賴關(guān)系,比如單元A依賴單元B,所以單元B要先于單元A編譯。你可以用#p?
ragma?? 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?? )?
等價(jià)于:?
#pragma?? warning(disable:4507?? 34)?? //?? 不顯示4507和34號警告信息?
#pragma?? warning(once:4385)?? //?? 4385號警告信息僅報(bào)告一次?
#pragma?? warning(error:164)?? //?? 把164號警告信息作為一個(gè)錯(cuò)誤。?
同時(shí)這個(gè)pragma?? warning?? 也支持如下格式:?
#pragma?? warning(?? push?? [?? ,n?? ]?? )?
#pragma?? warning(?? pop?? )?
這里n代表一個(gè)警告等級(1---4)。?
#pragma?? warning(?? push?? )保存所有警告信息的現(xiàn)有的警告狀態(tài)。?
#pragma?? warning(?? push,?? n)保存所有警告信息的現(xiàn)有的警告狀態(tài),并且把全局警告等級設(shè)定為n。?
#pragma?? warning(?? pop?? )向棧中彈出最后一個(gè)警告信息,在入棧和出棧之間所作的一切改動取消。例如:?
#pragma?? warning(?? push?? )?
#pragma?? warning(?? disable?? :?? 4705?? )?
#pragma?? warning(?? disable?? :?? 4706?? )?
#pragma?? warning(?? disable?? :?? 4707?? )?
//.......?
#pragma?? warning(?? pop?? )?
在這段代碼的最后,重新保存所有的警告信息(包括4705,4706和4707)。?
(7)pragma?? comment(...)?
該指令將一個(gè)注釋記錄放入一個(gè)對象文件或可執(zhí)行文件中。?常用的lib關(guān)鍵字,可以幫我們連入一個(gè)庫文件。?
(8)·通過#pragma?? pack(n)改變C編譯器的字節(jié)對齊方式???
在C語言中,結(jié)構(gòu)是一種復(fù)合數(shù)據(jù)類型,其構(gòu)成元素既可以是基本數(shù)據(jù)類型(如int、long、float等)的變量,也可以是一些復(fù)合數(shù)據(jù)類型(如數(shù)組、 結(jié)構(gòu)、聯(lián)合等)的數(shù)據(jù)單元。在結(jié)構(gòu)中,編譯器為結(jié)構(gòu)的每個(gè)成員按其自然對界(alignment)條件分配空間。各個(gè)成員按照它們被聲明的順序在內(nèi)存中順 序存儲,第一個(gè)成員的地址和整個(gè)結(jié)構(gòu)的地址相同。?
?????????? 例如,下面的結(jié)構(gòu)各成員空間分配情況:?
struct?? test???
{?
?????????? char?? x1;?
?????????? short?? x2;?
?????????? float?? x3;?
?????????? char?? x4;?
};?
?????????? 結(jié)構(gòu)的第一個(gè)成員x1,其偏移地址為0,占據(jù)了第1個(gè)字節(jié)。第二個(gè)成員x2為short類型,其起始地址必須2字節(jié)對界,因此,編譯器在x2和x1之間填 充了一個(gè)空字節(jié)。結(jié)構(gòu)的第三個(gè)成員x3和第四個(gè)成員x4恰好落在其自然對界地址上,在它們前面不需要額外的填充字節(jié)。在test結(jié)構(gòu)中,成員x3要求4字 節(jié)對界,是該結(jié)構(gòu)所有成員中要求的最大對界單元,因而test結(jié)構(gòu)的自然對界條件為4字節(jié),編譯器在成員x4后面填充了3個(gè)空字節(jié)。整個(gè)結(jié)構(gòu)所占據(jù)空間為 12字節(jié)。更改C編譯器的缺省字節(jié)對齊方式?
?????????? 在缺省情況下,C編譯器為每一個(gè)變量或是數(shù)據(jù)單元按其自然對界條件分配空間。一般地,可以通過下面的方法來改變?nèi)笔〉膶鐥l件:?
·?? 使用偽指令#pragma?? pack?? (n),C編譯器將按照n個(gè)字節(jié)對齊。?
?????????? ·?? 使用偽指令#pragma?? pack?? (),取消自定義字節(jié)對齊方式。?
?????????? 另外,還有如下的一種方式:?
?????????? ·?? __attribute((aligned?? (n))),讓所作用的結(jié)構(gòu)成員對齊在n字節(jié)自然邊界上。如果結(jié)構(gòu)中有成員的長度大于n,則按照最大成員的長度來對齊。?
?????????? ·?? __attribute__?? ((packed)),取消結(jié)構(gòu)在編譯過程中的優(yōu)化對齊,按照實(shí)際占用字節(jié)數(shù)進(jìn)行對齊。?
以上的n?? =?? 1,?? 2,?? 4,?? 8,?? 16...?? 第一種方式較為常見。?
應(yīng)用實(shí)例?
在網(wǎng)絡(luò)協(xié)議編程中,經(jīng)常會處理不同協(xié)議的數(shù)據(jù)報(bào)文。一種方法是通過指針偏移的方法來得到各種信息,但這樣做不僅編程復(fù)雜,而且一旦協(xié)議有變化,程序修 改起來也比較麻煩。在了解了編譯器對結(jié)構(gòu)空間的分配原則之后,我們完全可以利用這一特性定義自己的協(xié)議結(jié)構(gòu),通過訪問結(jié)構(gòu)的成員來獲取各種信息。這樣做, 不僅簡化了編程,而且即使協(xié)議發(fā)生變化,我們也只需修改協(xié)議結(jié)構(gòu)的定義即可,其它程序無需修改,省時(shí)省力。下面以TCP協(xié)議首部為例,說明如何定義協(xié)議結(jié) 構(gòu)。其協(xié)議結(jié)構(gòu)定義如下:?
#pragma?? pack(1)?? //?? 按照1字節(jié)方式進(jìn)行對齊?
struct?? TCPHEADER???
{?
?????????? short?? SrcPort;?? //?? 16位源端口號?
?????????? short?? DstPort;?? //?? 16位目的端口號?
?????????? int?? SerialNo;?? //?? 32位序列號?
?????????? int?? AckNo;?? //?? 32位確認(rèn)號?
?????????? unsigned?? char?? HaderLen?? :?? 4;?? //?? 4位首部長度?
?????????? unsigned?? char?? Reserved1?? :?? 4;?? //?? 保留6位中的4位?
?????????? unsigned?? char?? Reserved2?? :?? 2;?? //?? 保留6位中的2位?
?????????? unsigned?? char?? URG?? :?? 1;?
?????????? unsigned?? char?? ACK?? :?? 1;?
?????????? unsigned?? char?? PSH?? :?? 1;?
?????????? unsigned?? char?? RST?? :?? 1;?
?????????? unsigned?? char?? SYN?? :?? 1;?
?????????? unsigned?? char?? FIN?? :?? 1;?
?????????? short?? WindowSize;?? //?? 16位窗口大小?
?????????? short?? TcpChkSum;?? //?? 16位TCP檢驗(yàn)和?
?????????? short?? UrgentPointer;?? //?? 16位緊急指針?
};???
#pragma?? pack()?? //?? 取消1字節(jié)對齊方式????
總結(jié)
以上是生活随笔為你收集整理的#pragma comment和#pragma 预处理指令详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于WDM驱动开发的不错资料(来自cod
- 下一篇: GetCurrentProcessID、