c語言中巨集有兩個非常有用的巨集符號「#」「##」這兩個符號的用法總結如下。
#把巨集引數變為乙個字串而##把兩個巨集引數貼合在一起。
一、一般用法
#include
#define str(s) #s
#define conss(a,b) (int)a##e##b
int main()
二、巨集引數是另乙個巨集
1、非』#』和』##』的情況
#include
#define tow (2)
#define mul(a,b) (a*b)
int main()
展開的結果是
printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
所以沒有使用#符號時會遞迴的全部展開。
2、 當有』#』或』##』的時候
需要注意的是凡巨集定義裡有用』#』或』##』的地方巨集引數是不會再展開。如下
#include
#define int_max 0x7fffffff
#define str(s) #s
int main()
如果定義
#include
#define a (2)
#define conss(a,b) (int)a##e##b
int main()
則編譯時會報錯因為無法將a展開所以(int)(2)e(2)會出錯。
解決辦法加多一層中間轉換巨集。加這層巨集的用意是把所有巨集的引數在這層裡全部展開 那麼在轉換巨集裡
的那乙個巨集就能得到正確的巨集引數。
#include
#define a 2
#define _str(s) #s
#define str(s) _str(s) // 轉換巨集
#define _conss(a,b) (int)a##e##b
#define conss(a,b) _conss(a,b) // 轉換巨集
int main()
三、』#』和』##』的一些應用特例
1、合併匿名變數名
#define ___anonymous1(type, var, line) type var##line
#define __anonymous0(type, line) ___anonymous1(type, _anonymous, line)
#define anonymous(type) __anonymous0(type, __line__)
例anonymous(static int); 即: static int _anonymous70; 70表示該行行號
第一層anonymous(static int); --> __anonymous0(static int, __line__);
第二層 --> ___anonymous1(static int, _anonymous, 70);
第三層 --> static int _anonymous70;
即每次只能解開當前層的巨集所以__line__在第二層才能被解開
2、填充結構
#define fill(a)
enum idd;
typedef struct msgmsg;
msg _msg = ;
相當於
msg _msg = ,
};
3、記錄檔名
#define _get_file_name(f) #f
#define get_file_name(f) _get_file_name(f)
static char file_name = get_file_name(__file__);
4、得到乙個數值型別所對應的字串緩衝大小
#include
#define int_max 0x7fffffff
#define _type_buf_size(type) sizeof #type
#define type_buf_size(type) _type_buf_size(type)
int main()
相當於
type_buf_size(int_max)—>_type_buf_size(0x7fffffff)—>sizeof "0x7fffffff";
帶有可變引數的巨集( macros with a variable number of arguments )
在 1999 年版本的 iso c 標準中,巨集可以象函式一樣,定義時可以帶有可變引數。巨集的語法和函式的語法類似。下面有個例子:
#define debug(format, ...) fprintf (stderr, format, __va_args__)
這裡,『 … 』指可變引數。這類巨集在被呼叫時,它(這裡指『 … 』)被表示成零個或多個符號,包括裡面的逗號,一直到到右括弧結束為止。當被呼叫時,在巨集體( macro body )中,那些符號串行集合將代替裡面的 __va_args__ 識別符號。更多的資訊可以參考 cpp 手冊。
gcc 始終支援複雜的巨集,它使用一種不同的語法從而可以使你可以給可變引數乙個名字,如同其它引數一樣。例如下面的例子:
#define debug(format, args...) fprintf (stderr, format, args)
這和上面舉的那個 iso c 定義的巨集例子是完全一樣的,但是這麼寫可讀性更強並且更容易進行描述。
gnu cpp 還有兩種更複雜的巨集擴充套件,支援上面兩種格式的定義格式。
在標準 c 裡,你不能省略可變引數,但是你卻可以給它傳遞乙個空的引數。例如,下面的巨集呼叫在 iso c 裡是非法的,因為字串後面沒有逗號:
debug ("a message")
gnu cpp 在這種情況下可以讓你完全的忽略可變引數。在上面的例子中,編譯器仍然會有問題( complain ),因為巨集展開後,裡面的字串後面會有個多餘的逗號。
為了解決這個問題, cpp 使用乙個特殊的『 ## 』操作。書寫格式為:
#define debug(format, ...) fprintf (stderr, format, ## __va_args__)
這裡,如果可變引數被忽略或為空,『 ## 』操作將使預處理器( preprocessor )去除掉它前面的那個逗號。如果你在巨集呼叫時,確實提供了一些可變引數, gnu cpp 也會工作正常,它會把這些可變引數放到逗號的後面。象其它的 pasted macro 引數一樣,這些引數不是巨集的擴充套件。
c語言中巨集定義的用法
1 帶有 d的巨集,一般用於make中 ifndef svn base svn base ver info svn base endif ver info svn base是變數,型別是整數 ver info ver no 是變數,型別是字串 processor cflags d comp date...
c語言解除巨集定義 C語言中巨集定義的用法
說到巨集定義,我們應該先了解什麼是預處理指令,相信大家並不會陌生,之前我們程式設計時,程式的開頭 include指令,define指令都是預處理指令,它能使我們的編譯更加的高效,便捷,因此c語言中是允許使用者自己加入一些特定的預處理指令的。一,不帶引數的巨集定義 不帶引數的巨集定義是比較簡單的,就是...
c 語言中的巨集定義
巨集定義 巨集定義是c提供的三種預處理功能的其中一種,這三種預處理包括 巨集定義 檔案包含 條件編譯 1.不帶引數的巨集定義 巨集定義又稱為巨集代換 巨集替換,簡稱 巨集 格式 define 識別符號 字串 其中的識別符號就是所謂的 符號常量,也稱為 巨集名 預處理 預編譯 工作也叫做巨集展開 將巨...