C語言中巨集定義 和 符號的用法

2021-07-11 10:28:00 字數 3470 閱讀 3418

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 識別符號 字串 其中的識別符號就是所謂的 符號常量,也稱為 巨集名 預處理 預編譯 工作也叫做巨集展開 將巨...