c/c++标准预定义宏
轉(zhuǎn)自:http://www.eefocus.com/andysun001/blog/10-06/192018_008b3.html
?
一、標(biāo)準(zhǔn)預(yù)定義宏
The standard predefined macros are specified by the relevant language standards, so they are available with all compilers that implement those standards. Older compilers may not provide all of them. Their names all start with double underscores.
__FILE__
This macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the short name specified in #include or as the input file name argument. For example, "/usr/local/include/myheader.h" is a possible expansion of this macro.
__LINE__
This macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it's a pretty strange macro, since its "definition" changes with each new line of source code.
__FILE__ and __LINE__ are useful in generating an error message to report an inconsistency detected by the program; the message can state the source line at which the inconsistency was detected. For example,
???? fprintf (stderr, "Internal error: "
????????????????????? "negative string length "
????????????????????? "%d at %s, line %d.",
????????????? length, __FILE__, __LINE__);
????
An #include directive changes the expansions of __FILE__ and __LINE__ to correspond to the included file. At the end of that file, when processing resumes on the input file that contained the #include directive, the expansions of __FILE__ and __LINE__ revert to the values they had before the #include (but __LINE__ is then incremented by one as processing moves to the line after the #include).
A #line directive changes __LINE__, and may change __FILE__ as well. See Line Control.
C99 introduces __func__, and GCC has provided __FUNCTION__ for a long time. Both of these are strings containing the name of the current function (there are slight semantic differences; see the GCC manual). Neither of them is a macro; the preprocessor does not know the name of the current function. They tend to be useful in conjunction with __FILE__ and __LINE__, though.
__DATE__
This macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left.
If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".
__TIME__
This macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like "23:59:01".
If GCC cannot determine the current time, it will emit a warning message (once per compilation) and __TIME__ will expand to "??:??:??".
__STDC__
In normal operation, this macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C. If GNU CPP is used with a compiler other than GCC, this is not necessarily true; however, the preprocessor always conforms to the standard unless the -traditional-cpp option is used.
This macro is not defined if the -traditional-cpp option is used.
On some hosts, the system compiler uses a different convention, where __STDC__ is normally 0, but is 1 if the user specifies strict conformance to the C Standard. CPP follows the host convention when processing system header files, but when processing user files __STDC__ is always 1. This has been reported to cause problems; for instance, some versions of Solaris provide X Windows headers that expect __STDC__ to be either undefined or 1. See Invocation.
__STDC_VERSION__
This macro expands to the C Standard's version number, a long integer constant of the form yyyymmL where yyyy and mm are the year and month of the Standard version. This signifies which version of the C Standard the compiler conforms to. Like __STDC__, this is not necessarily accurate for the entire implementation, unless GNU CPP is being used with GCC.
The value 199409L signifies the 1989 C standard as amended in 1994, which is the current default; the value 199901L signifies the 1999 revision of the C standard. Support for the 1999 revision is not yet complete.
This macro is not defined if the -traditional-cpp option is used, nor when compiling C++ or Objective-C.
__STDC_HOSTED__
This macro is defined, with value 1, if the compiler's target is a hosted environment. A hosted environment has the complete facilities of the standard C library available.
__cplusplus
This macro is defined when the C++ compiler is in use. You can use __cplusplus to test whether a header is compiled by a C compiler or a C++ compiler. This macro is similar to __STDC_VERSION__, in that it expands to a version number. A fully conforming implementation of the 1998 C++ standard will define this macro to 199711L. The GNU C++ compiler is not yet fully conforming, so it uses 1 instead. We hope to complete our implementation in the near future.
__OBJC__
This macro is defined, with value 1, when the Objective-C compiler is in use. You can use __OBJC__ to test whether a header is compiled by a C compiler or a Objective-C compiler.
__ASSEMBLER__
This macro is defined with value 1 when preprocessing assembly language.
?
C標(biāo)準(zhǔn)中的一些預(yù)定義宏昨天寫(xiě)代碼時(shí)需要在代碼獲取當(dāng)前編譯時(shí)間,從而可動(dòng)態(tài)地作為版本信息,因此用到了C標(biāo)準(zhǔn)中的一些預(yù)定義的宏。在此將C標(biāo)準(zhǔn)中定義的幾個(gè)宏一并總結(jié)一下:
?
__DATE__ 進(jìn)行預(yù)處理的日期(“Mmm dd yyyy”形式的字符串文字,如May 27 2006)
__FILE__ 代表當(dāng)前源代碼文件名的字符串文字 ,包含了詳細(xì)路徑,如G:/program/study/c+/test1.c
__LINE__ 代表當(dāng)前源代碼中的行號(hào)的整數(shù)常量
__TIME__ 源文件編譯時(shí)間,格式微“hh:mm:ss”,如:09:11:10;
__func__ 當(dāng)前所在函數(shù)名,在編譯器的較高版本中支持
__FUNCTION__ 當(dāng)前所在函數(shù)名
對(duì)于__FILE__,__LINE__,__func__,__FUNCTION__ 這樣的宏,在調(diào)試程序時(shí)是很有用的,因?yàn)槟憧梢院苋菀椎闹莱绦蜻\(yùn)行到了哪個(gè)文件的那一行,是哪個(gè)函數(shù)。
而對(duì)于__DATE__,__TIME__則可以獲取編譯時(shí)間,如如下代碼通過(guò)宏獲取編譯時(shí)間,并通過(guò)sscanf()從中獲取具體的年月日時(shí)分秒數(shù)據(jù),可在代碼中做相應(yīng)使用。我的代碼中是根據(jù)此數(shù)據(jù)作為版本標(biāo)識(shí),并依此判斷哪個(gè)版本新些及是否需要升級(jí)。
char * creationDate?? = __DATE__ ", " __TIME__;
sscanf(creationDate, "%s %d %d, %d:%d:%d", month, &day, &year, &hour, &min, &sec);
?
?
預(yù)處理命令#pragma和預(yù)定義宏--轉(zhuǎn)載
一、C預(yù)定義宏
C標(biāo)準(zhǔn)指定了一些預(yù)定義宏,編程中常常用到。
__DATE__???? 進(jìn)行預(yù)處理的日期
__FILE__???? 代表當(dāng)前源代碼文件名的字符串
__LINE__???? 代表當(dāng)前源代碼文件中行號(hào)的整數(shù)常量
__STDC__???? 設(shè)置為1時(shí),表示該實(shí)現(xiàn)遵循C標(biāo)準(zhǔn)
__STDC_HOSTED__? 為本機(jī)環(huán)境設(shè)置為,否則設(shè)為0
__STDC_VERSION__ 為C99時(shí)設(shè)置為199901L
__TIME__???? 源文件的編譯時(shí)間
__func__???? C99提供的,為所在函數(shù)名的字符串
對(duì)于__FILE__,__LINE__,__func__這樣的宏,在調(diào)試程序時(shí)是很有用的,因?yàn)槟憧梢院苋菀椎闹莱绦蜻\(yùn)行到了哪個(gè)文件的那一行,是哪個(gè)函數(shù).
例如:
#include
#include
void why_me();
int main()
{
??? printf( "The file is %s/n", __FILE__ );
??? printf( "The date is %s/n", __DATE__ );
??? printf( "The time is %s/n", __TIME__ );
??? printf("The version is %s/n",__STDC__VERSION__);
??? printf( "This is line %d/n", __LINE__ );
??? printf( "This function is %s/n ", __func__ );
?? why_me();
?? return 0;
}
void why_me()
{
??? printf( "This function is %s/n", __func__ );
??? printf( "This is line %d/n", __LINE__ );
}
二、#line和#error
#line用于重置由__LINE__和__FILE__宏指定的行號(hào)和文件名。
用法如下:#line number filename
例如:#line 1000 //將當(dāng)前行號(hào)設(shè)置為1000
?????#line 1000 "lukas.c"?? //行號(hào)設(shè)置為1000,文件名設(shè)置為lukas.c
#error指令使預(yù)處理器發(fā)出一條錯(cuò)誤消息,該消息包含指令中的文本.這條指令的目的就是在程序崩潰之前能夠給出一定的信息。
三、#pragma
在所有的預(yù)處理指令中,#Pragma 指令可能是最復(fù)雜的了。#pragma的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動(dòng)作。#pragma指令對(duì)每個(gè)編譯器給出了一個(gè)方法,在保持與C和C++語(yǔ)言完全兼容的情況下,給出主機(jī)或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機(jī)器或操作系統(tǒng)專有的,且對(duì)于每個(gè)編譯器都是不同的。
其格式一般為: #Pragma Para
其中Para 為參數(shù),下面來(lái)看一些常用的參數(shù)。
(1)message 參數(shù)。 Message 參數(shù)是我最喜歡的一個(gè)參數(shù),它能夠在編譯信息輸出窗口中輸出相應(yīng)的信息,這對(duì)于源代碼信息的控制是非常重要的。其使用方法為:
#Pragma message(“消息文本”)
當(dāng)編譯器遇到這條指令時(shí)就在編譯輸出窗口中將消息文本打印出來(lái)。
當(dāng)我們?cè)诔绦蛑卸x了許多宏來(lái)控制源代碼版本的時(shí)候,我們自己有可能都會(huì)忘記有沒(méi)有正確的設(shè)置這些宏,此時(shí)我們可以用這條指令在編譯的時(shí)候就進(jìn)行檢查。假設(shè)我們希望判斷自己有沒(méi)有在源代碼的什么地方定義了_X86這個(gè)宏可以用下面的方法
#ifdef _X86
#Pragma message(“_X86 macro activated!”)
#endif
當(dāng)我們定義了_X86這個(gè)宏以后,應(yīng)用程序在編譯時(shí)就會(huì)在編譯輸出窗口里顯示“_
X86 macro activated!”。我們就不會(huì)因?yàn)椴挥浀米约憾x的一些特定的宏而抓耳撓腮了。
(2)另一個(gè)使用得比較多的pragma參數(shù)是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開(kāi)發(fā)驅(qū)動(dòng)程序的時(shí)候就會(huì)使用到它。
(3)#pragma once (比較常用)
只要在頭文件的最開(kāi)始加入這條指令就能夠保證頭文件被編譯一次。這條指令實(shí)際上在VC6中就已經(jīng)有了,但是考慮到兼容性并沒(méi)有太多的使用它。
(4)#pragma hdrstop表示預(yù)編譯頭文件到此為止,后面的頭文件不進(jìn)行預(yù)編譯。BCB可以預(yù)編譯頭文件以加快鏈接的速度,但如果所有頭文件都進(jìn)行預(yù)編譯又可能占太多磁盤(pán)空間,所以使用這個(gè)選項(xiàng)排除一些頭文件。
有時(shí)單元之間有依賴關(guān)系,比如單元A依賴單元B,所以單元B要先于單元A編譯。你可以用#pragma startup指定編譯優(yōu)先級(jí),如果使用了#pragma package(smart_init) ,BCB就會(huì)根據(jù)優(yōu)先級(jí)的大小先后編譯。
(5)#pragma resource "*.dfm"表示把*.dfm文件中的資源加入工程。*.dfm中包括窗體外觀的定義。
(6)#pragma warning( disable : 4507 34; once : 4385; error : 164 )等價(jià)于:
#pragma warning(disable:4507 34) /* 不顯示4507和34號(hào)警告信息。如果編譯時(shí)總是出現(xiàn)4507號(hào)警告和34號(hào)警告,
????????????????????????????????????而認(rèn)為肯定不會(huì)有錯(cuò)誤,可以使用這條指令。*/
#pragma warning(once:4385) // 4385號(hào)警告信息僅報(bào)告一次
#pragma warning(error:164) // 把164號(hào)警告信息作為一個(gè)錯(cuò)誤。
同時(shí)這個(gè)pragma warning 也支持如下格式:
#pragma warning( push [ ,n ] )
#pragma warning( pop )
這里n代表一個(gè)警告等級(jí)(1---4)。
#pragma warning( push )保存所有警告信息的現(xiàn)有的警告狀態(tài)。
#pragma warning( push, n)保存所有警告信息的現(xiàn)有的警告狀態(tài),并且把全局警告等級(jí)設(shè)定為n。
#pragma warning( pop )向棧中彈出最后一個(gè)警告信息,在入棧和出棧之間所作的一切改動(dòng)取消。例如:
#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è)對(duì)象文件或可執(zhí)行文件中。
常用的lib關(guān)鍵字,可以幫我們連入一個(gè)庫(kù)文件。
(8)progma pack(n)
??? 指定結(jié)構(gòu)體對(duì)齊方式!#pragma pack(n)來(lái)設(shè)定變量以n字節(jié)對(duì)齊方式。n 字節(jié)對(duì)齊就是說(shuō)變量存放的起始地址的偏移量有兩種情況:第一、如果n大于等于該變量所占用的字節(jié)數(shù),那么偏移量必須滿足默認(rèn)的對(duì)齊方式,第二、如果n小于該變量的類(lèi)型所占用的字節(jié)數(shù),那么偏移量為n的倍數(shù),不用滿足默認(rèn)的對(duì)齊方式。結(jié)構(gòu)的總大小也有個(gè)約束條件,分下面兩種情況:如果n大于所有成員變量類(lèi)型所占用的字節(jié)數(shù),那么結(jié)構(gòu)的總大小必須為占用空間最大的變量占用的空間數(shù)的倍數(shù); 否則必須為n的倍數(shù)。下面舉例說(shuō)明其用法。
#pragma pack(push) //保存對(duì)齊狀態(tài)
#pragma pack(4)//設(shè)定為4字節(jié)對(duì)齊
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢復(fù)對(duì)齊狀態(tài)
為測(cè)試該功能,可以使用sizeof()測(cè)試結(jié)構(gòu)體的長(zhǎng)度!
?
?
?在你寫(xiě)dll的時(shí)候,因?yàn)閷?duì)于C和C++,編譯器會(huì)有不同的名字解析規(guī)則,所以可以這樣用
#ifndef ? __STDC__
extern "C " ? void ? function();
#else
void ? function();
#endif
?
?__LINE__?????????? 在源代碼中插入當(dāng)前源代碼行號(hào)
? __FILE__?????????? 在源代碼中插入當(dāng)前源代碼文件名
? __DATE__?????????? 在源代碼中插入當(dāng)前編譯日期〔注意和當(dāng)前系統(tǒng)日期區(qū)別開(kāi)來(lái)〕
? __TIME__?????????? 在源代碼中插入當(dāng)前編譯時(shí)間〔注意和當(dāng)前系統(tǒng)時(shí)間區(qū)別開(kāi)來(lái)〕??
? __STDC__?????????? 當(dāng)要求程序嚴(yán)格遵循ANSIC標(biāo)準(zhǔn)時(shí)該標(biāo)識(shí)符被賦值為1。
----------------------------------------------------------------------------
標(biāo)識(shí)符__LINE__和__FILE__通常用來(lái)調(diào)試程序;標(biāo)識(shí)符__DATE__和__TIME__通常用來(lái)在編譯后的程序中加入一個(gè)時(shí)間標(biāo)志,以區(qū)分程序的不同版本;當(dāng)要求程序嚴(yán)格遵循ANSIC標(biāo)準(zhǔn)時(shí),標(biāo)識(shí)符__STDC__就會(huì)被賦值為1;當(dāng)用C++編譯程序編譯時(shí),標(biāo)識(shí)符__cplusplus就會(huì)被定義。
#include
?
int main ()
{
??? printf("該輸出行在源程序中的位置:%d/n", __LINE__ );
??? printf("該程序的文件名為:%s/n", __FILE__ );
??? printf("當(dāng)前日期為:%s/n", __DATE__ );
??? printf("當(dāng)前時(shí)間為:%s/n", __TIME__ );
?
??? return 0;
}
?
#include
void main(void)
{
??? printf("%d",__LINE__); // Line 5
}
結(jié)果為:5
?
?
// 標(biāo)準(zhǔn)預(yù)定義宏宏.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include
void main(void)
{
???? printf("%d",__LINE__); // Line 5
?}
?
?
編譯器宏使用總結(jié)
C/C++中宏總結(jié)C程序的源代碼中可包括各種編譯指令,這些指令稱為預(yù)處理命令。雖然它們實(shí)際上不是C語(yǔ)言的一部分,但卻擴(kuò)展了C程序設(shè)計(jì)的環(huán)境。本節(jié)將介紹如何應(yīng)用預(yù)處理程序和注釋簡(jiǎn)化程序開(kāi)發(fā)過(guò)程,并提高程序的可讀性。ANSI標(biāo)準(zhǔn)定義的C語(yǔ)言預(yù)處理程序包括下列命令:
?
#define,#error,#include,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。非常明顯,所有預(yù)處理命令均以符號(hào)#開(kāi)頭,下面分別加以介紹。
?
命令#define定義了一個(gè)標(biāo)識(shí)符及一個(gè)串。在源程序中每次遇到該標(biāo)識(shí)符時(shí),均以定義的串代換它。ANSI標(biāo)準(zhǔn)將標(biāo)識(shí)符定義為宏名,將替換過(guò)程稱為宏替換。命令的一般形式為:
?
#define identifier string
?
注意:
? 該語(yǔ)句沒(méi)有分號(hào)。在標(biāo)識(shí)符和串之間可以有任意個(gè)空格,串一旦開(kāi)始,僅由一新行結(jié)束。
? 宏名定義后,即可成為其它宏名定義中的一部分。
? 宏替換僅僅是以文本串代替宏標(biāo)識(shí)符,前提是宏標(biāo)識(shí)符必須獨(dú)立的識(shí)別出來(lái),否則不進(jìn)行替換。例如:
#define XYZ this is a tes
使用宏printf("XYZ");//該段不打印"this is a test"而打印"XYZ"。因?yàn)轭A(yù)編譯器識(shí)別出的是"XYZ"
? 如果串長(zhǎng)于一行,可以在該行末尾用一反斜杠' /'續(xù)行。
?
處理器命令#error強(qiáng)迫編譯程序停止編譯,主要用于程序調(diào)試。
?
#include 命令#i nclude使編譯程序?qū)⒘硪辉次募度霂в?#xff03;i nclude的源文件,被讀入的源文件必須用雙引號(hào)或尖括號(hào)括起來(lái)。例如:
?
#i nclude"stdio.h"或者#i nclude
?
這兩行代碼均使用C編譯程序讀入并編譯用于處理磁盤(pán)文件庫(kù)的子程序。
將文件嵌入#i nclude命令中的文件內(nèi)是可行的,這種方式稱為嵌套的嵌入文件,嵌套層次依賴于具體實(shí)現(xiàn)。
?
如果顯式路徑名為文件標(biāo)識(shí)符的一部分,則僅在哪些子目錄中搜索被嵌入文件。否則,如果文件名用雙引號(hào)括起來(lái),則首先檢索當(dāng)前工作目錄。如果未發(fā)現(xiàn)文件,則在命令行中說(shuō)明的所有目錄中搜索。如果仍未發(fā)現(xiàn)文件,則搜索實(shí)現(xiàn)時(shí)定義的標(biāo)準(zhǔn)目錄。
?
如果沒(méi)有顯式路徑名且文件名被尖括號(hào)括起來(lái),則首先在編譯命令行中的目錄內(nèi)檢索。
?
如果文件沒(méi)找到,則檢索標(biāo)準(zhǔn)目錄,不檢索當(dāng)前工作目錄。
?
條件編譯命令
有幾個(gè)命令可對(duì)程序源代碼的各部分有選擇地進(jìn)行編譯,該過(guò)程稱為條件編譯。商業(yè)軟件公司廣泛應(yīng)用條件編譯來(lái)提供和維護(hù)某一程序的許多顧客版本。
?
#if、#else,#elif及#endif
?
#if的一般含義是如果#if后面的常量表達(dá)式為true,則編譯它與#endif之間的代碼,否則跳過(guò)這些代碼。命令#endif標(biāo)識(shí)一個(gè)#if塊的結(jié)束。
?
#if constant-expression
statement sequence
#endif
?
跟在#if后面的表達(dá)式在編譯時(shí)求值,因此它必須僅含常量及已定義過(guò)的標(biāo)識(shí)符,不可使用變量。表達(dá)式不許含有操作符sizeof(sizeof也是編譯時(shí)求值)。
?
#else命令的功能有點(diǎn)象C語(yǔ)言中的else;#else建立另一選擇(在#if失敗的情況下)。注意,# else屬于# if塊。
?
#elif命令意義與ELSE IF 相同,它形成一個(gè)if else-if階梯狀語(yǔ)句,可進(jìn)行多種編譯選擇。#elif 后跟一個(gè)常量表達(dá)式。如果表達(dá)式為true,則編譯其后的代碼塊,不對(duì)其它#elif表達(dá)式進(jìn)行測(cè)試。否則,順序測(cè)試下一塊。
?
#if expression
statement sequence
#elif expression1
statement sequence
#endif
?
在嵌套的條件編譯中#endif、#else或#elif與最近#if或#elif匹配。
?
# ifdef 和# ifndef
?
條件編譯的另一種方法是用#ifdef與#ifndef命令,它們分別表示"如果有定義"及"如果無(wú)定義"。# ifdef的一般形式是:
?
# ifdef macroname
statement sequence
#endif
?
#ifdef與#ifndef可以用于#if、#else,#elif語(yǔ)句中,但必須與一個(gè)#endif。
?
命令#undef 取消其后那個(gè)前面已定義過(guò)有宏名定義。一般形式為:
#undef macroname
?
命令# line改變__LINE__與__FILE__的內(nèi)容,它們是在編譯程序中預(yù)先定義的標(biāo)識(shí)符。命令的基本形式如下:
?
# line number["filename"]
?
其中的數(shù)字為任何正整數(shù),可選的文件名為任意有效文件標(biāo)識(shí)符。行號(hào)為源程序中當(dāng)前行號(hào),文件名為源文件的名字。命令# line主要用于調(diào)試及其它特殊應(yīng)用。注意:在#line后面的數(shù)字標(biāo)識(shí)從下一行開(kāi)始的數(shù)字標(biāo)識(shí)。
?
預(yù)定義的宏名
?
ANSI標(biāo)準(zhǔn)說(shuō)明了C中的五個(gè)預(yù)定義的宏名。它們是:
?
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__
?
如果編譯不是標(biāo)準(zhǔn)的,則可能僅支持以上宏名中的幾個(gè),或根本不支持。記住編譯程序也許還提供其它預(yù)定義的宏名。
?
__LINE__及__FILE__宏指令在有關(guān)# line的部分中已討論,這里討論其余的宏名。
__DATE__宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時(shí)的日期。
源代碼翻譯到目標(biāo)代碼的時(shí)間作為串包含在__TIME__中。串形式為時(shí):分:秒。
如果實(shí)現(xiàn)是標(biāo)準(zhǔn)的,則宏__STDC__含有十進(jìn)制常量1。如果它含有任何其它數(shù),則實(shí)現(xiàn)是非標(biāo)準(zhǔn)的。編譯C++程序時(shí),編譯器自動(dòng)定義了一個(gè)預(yù)處理名字__cplusplus,而編譯標(biāo)準(zhǔn)C時(shí),自動(dòng)定義名字__STDC__。
?
注意:宏名的書(shū)寫(xiě)由標(biāo)識(shí)符與兩邊各二條下劃線構(gòu)成。
?
(部分內(nèi)容出自:http://www.bc-cn.net/Article/kfyy/cyy/jc/200511/919.html) 8、
?
C、C++宏體中出現(xiàn)的#,#@,##
?
宏體中,#的功能是將其后面的宏參數(shù)進(jìn)行字符串化操作(Stringfication),簡(jiǎn)單說(shuō)就是在對(duì)它所引用的宏變量通過(guò)替換后在其左右各加上一個(gè)雙引號(hào)。
?
而##被稱為連接符(concatenator),用來(lái)將兩個(gè)Token連接為一個(gè)Token。注意這里連接的對(duì)象是Token就行,而不一定是宏的變量。比如你要做一個(gè)菜單項(xiàng)命令名和函數(shù)指針組成的結(jié)構(gòu)體。
http://baike.baidu.com/view/3487831.htm
#pragma comment( comment-type ,["commentstring"] )
comment-type是一個(gè)預(yù)定義的標(biāo)識(shí)符,指定注釋的類(lèi)型,應(yīng)該是compiler,exestr,lib,linker之一。
commentstring是一個(gè)提供為comment-type提供附加信息的字符串。
注釋類(lèi)型:
1、compiler:
放置編譯器的版本或者名字到一個(gè)對(duì)象文件,該選項(xiàng)是被linker忽略的。
2、exestr:
在以后的版本將被取消。
3、lib:
放置一個(gè)庫(kù)搜索記錄到對(duì)象文件中,這個(gè)類(lèi)型應(yīng)該是和commentstring(指定你要Linker搜索的lib的名稱和路徑)這個(gè)庫(kù)的名字放在Object文件的默認(rèn)庫(kù)搜索記錄的后面,linker搜索這個(gè)這個(gè)庫(kù)就像你在命令行輸入這個(gè)命令一樣。你可以在一個(gè)源文件中設(shè)置多個(gè)庫(kù)記錄,它們?cè)趏bject文件中的順序和在源文件中的順序一樣。如果默認(rèn)庫(kù)和附加庫(kù)的次序是需要區(qū)別的,使用Z編譯開(kāi)關(guān)是防止默認(rèn)庫(kù)放到object模塊。
4、linker:
指定一個(gè)連接選項(xiàng),這樣就不用在命令行輸入或者在開(kāi)發(fā)環(huán)境中設(shè)置了。
只有下面的linker選項(xiàng)能被傳給Linker.
/DEFAULTLIB ,/EXPORT,/INCLUDE,/MANIFESTDEPENDENCY, /MERGE,/SECTION
(1) /DEFAULTLIB:library
/DEFAULTLIB 選項(xiàng)將一個(gè) library 添加到 LINK 在解析引用時(shí)搜索的庫(kù)列表。用 /DEFAULTLIB指定的庫(kù)在命令行上指定的庫(kù)之后和 .obj 文件中指定的默認(rèn)庫(kù)之前被搜索。忽略所有默認(rèn)庫(kù) (/NODEFAULTLIB) 選項(xiàng)重寫(xiě) /DEFAULTLIB:library。如果在兩者中指定了相同的 library 名稱,忽略庫(kù) (/NODEFAULTLIB:library) 選項(xiàng)將重寫(xiě) /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 的索引;如果沒(méi)有指定 ordinal,則 LINK 將分配一個(gè)。NONAME 關(guān)鍵字只將函數(shù)導(dǎo)出為序號(hào),沒(méi)有 entryname。
DATA 關(guān)鍵字指定導(dǎo)出項(xiàng)為數(shù)據(jù)項(xiàng)。客戶程序中的數(shù)據(jù)項(xiàng)必須用 extern __declspec(dllimport) 來(lái)聲明。
有三種導(dǎo)出定義的方法,按照建議的使用順序依次為:
源代碼中的 __declspec(dllexport).def 文件中的 EXPORTS 語(yǔ)句LINK 命令中的 /EXPORT 規(guī)范所有這三種方法可以用在同一個(gè)程序中。LINK 在生成包含導(dǎo)出的程序時(shí)還創(chuàng)建導(dǎo)入庫(kù),除非生成中使用了 .exp 文件。
LINK 使用標(biāo)識(shí)符的修飾形式。編譯器在創(chuàng)建 .obj 文件時(shí)修飾標(biāo)識(shí)符。如果 entryname 以其未修飾的形式指定給鏈接器(與其在源代碼中一樣),則 LINK 將試圖匹配該名稱。如果無(wú)法找到唯一的匹配名稱,則 LINK 發(fā)出錯(cuò)誤信息。當(dāng)需要將標(biāo)識(shí)符指定給鏈接器時(shí),請(qǐng)使用 Dumpbin 工具獲取該標(biāo)識(shí)符的修飾名形式。
(3)/INCLUDE:symbol
/INCLUDE 選項(xiàng)通知鏈接器將指定的符號(hào)添加到符號(hào)表。
若要指定多個(gè)符號(hào),請(qǐng)?jiān)诜?hào)名稱之間鍵入逗號(hào) (,)、分號(hào) (;) 或空格。在命令行上,對(duì)每個(gè)符號(hào)指定一次 /INCLUDE:symbol。
鏈接器通過(guò)將包含符號(hào)定義的對(duì)象添加到程序來(lái)解析 symbol。該功能對(duì)于添包含不會(huì)鏈接到程序的庫(kù)對(duì)象非常有用。用該選項(xiàng)指定符號(hào)將通過(guò) /OPT:REF 重寫(xiě)該符號(hào)的移除。
我們經(jīng)常用到的是#pragma comment(lib,"*.lib")這類(lèi)的。#pragma comment(lib,"Ws2_32.lib")表示鏈接Ws2_32.lib這個(gè)庫(kù)。 和在工程設(shè)置里寫(xiě)上鏈入Ws2_32.lib的效果一樣,不過(guò)這種方法寫(xiě)的 程序別人在使用你的代碼的時(shí)候就不用再設(shè)置工程settings了
總結(jié)
以上是生活随笔為你收集整理的c/c++标准预定义宏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: OpenCV 2.2.0 CvvImag
- 下一篇: 解决:VS 2005/2008 中 fs