#define 的高級用法

原文:http://blog.csdn.net/newthinker_wei/article/details/8893407

一、LINUX C中用define定義可變參數的宏


一般在調試打印Debug信息的時候, 需要可變參數的宏. 從C99開始可以使編譯器標準支持可變參數宏(variadic macros), 另外GCC也支持可變參數宏, 但是兩種在細節上可能存在區別.
1. __VA_ARGS__
        __VA_ARGS__ 將 "..." 傳遞給宏 . 如
        #define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)

2. GCC的複雜宏
        GCC使用一種不同的語法,從而可以給可變參數一個名字,如同其它參數一樣.
        #define debug(format, args...) fprintf (stderr, format, args)
        這和第一條的宏例子是完全一樣的,但是這麼寫可讀性更強並且更容易進行描述.

3. ##__VA_ARGS__
        上面兩個定義的宏,如果出現 debug("A Message")的時候,由於宏展開後有個多餘的逗號,所以將導致編譯錯誤.
        爲了解決這個問題,CPP 使用一個特殊的"##"操作,格式如下:
        #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
        這裏,如果可變參數被忽略或爲空,"##"操作將使預處理器(preprocessor)去除掉它前面的那個逗號.


上文來自:http://blog.chinaunix.net/uid-17240700-id-2813911.html



二、define宏定義中的#,##,@#及\符號


1、# (stringizing)字符串化操作符。

其作用是:將宏定義中的傳入參數名轉換成用一對雙引號括起來參數名字符串。其只能用於有傳入參數的宏定義中,且必須置於宏定義體中的參數名前。

如:

#define example(instr) printf("the input string is:\t%s\n",#instr)

#define example1(instr) #instr

當使用該宏定義時:

example(abc); 在編譯時將會展開成:printf("the input string is:\t%s\n","abc");

string str=example1(abc); 將會展成:string str="abc";

注意:

對空格的處理

a。忽略傳入參數名前面和後面的空格。

   如:str=example1(   abc ); 將會被擴展成 str="abc";

b.當傳入參數名間存在空格時,編譯器將會自動連接各個子字符串,用每個子字符串中只以一個空格連接,忽略其中多餘一個的空格。

   如:str=exapme( abc    def); 將會被擴展成 str="abc def";

 2、## (token-pasting)符號連接操作符

宏定義中:參數名,即爲形參,如#define sum(a,b) (a+b);中a和b均爲某一參數的代表符號,即形式參數。

而##的作用則是將宏定義的多個形參成一個實際參數名。

如:

#define exampleNum(n) num##n

int num9=9;

使用:

int num=exampleNum(9); 將會擴展成 int num=num9;

注意:

1.當用##連接形參時,##前後的空格可有可無。

如:#define exampleNum(n) num ## n 相當於 #define exampleNum(n) num##n

2.連接後的實際參數名,必須爲實際存在的參數名或是編譯器已知的宏定義

// preprocessor_token_pasting.cpp

#include <stdio.h>

#define paster( n ) printf_s( "token" #n " = %d", token##n )

int token9 = 9;

 int main()

{

   paster(9);

}

運行結果:

token9 = 9

 3、@# (charizing)字符化操作符。

只能用於有傳入參數的宏定義中,且必須置於宏定義體中的參數名前。作用是將傳的單字符參數名轉換成字符,以一對單引用括起來。

#define makechar(x)  #@x

a = makechar(b);

展開後變成了:

a= 'b';

 

4、\ 行繼續操作符

當定義的宏不能用一行表達完整時,可以用"\"表示下一行繼續此宏的定義。



上文來自:http://hi.baidu.com/lowen_pig/item/1163b2d530cbec826dce3f8a



附:編譯器內置宏(補充於2014.03.31)

ANSI C標準中有幾個標準預定義宏(也是常用的):

__LINE__:在源代碼中插入當前源代碼行號;

__FILE__:在源文件中插入當前源文件名;

__DATE__:在源文件中插入當前的編譯日期

__TIME__:在源文件中插入當前編譯時間;

__STDC__:當要求程序嚴格遵循ANSI C標準時該標識被賦值爲1;

__cplusplus:當編寫C++程序時該標識符被定義。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章