巨集定義中等的用法

2022-10-15 17:54:12 字數 3701 閱讀 5479

c語言巨集定義中"#","#@"和"##"的用法

#definemacro(a)#a

#definemacro2(a,b)a##b

#definemacro3(a,b,c)a##b##c

#a, 表示a不再是乙個變數, 而變成了字串"a"

##表示連線, a##b, 表示輸入的引數名為ab, a##b##c同理, 代表變數名為: abc

測試例子:

intx=3;

inty=4;

intxy=10;

intxyz=20;

cstringstr;

outputdebugstring(macro(x));

"%d",macro2(x,y));

outputdebugstring(str);

"%d",macro3(x,y,z));

outputdebugstring(str);

輸出結果為:x10

20第乙個為x, marco(x), x變成了"x"字串

第二個為10, macro(x,y), 就是變數xy

第三個為20, macro(x,y,z), 就是變數xyz

#把巨集引數變為乙個字串,#@把巨集引數變為乙個字元,##把兩個巨集引數貼合在一起。

#include <>

#include <>

#define str(s) #s與引數之間可以有空格

#define tochar(c) #@c

#define cons(a,b) int(a##e##b與引數之間可以有空格

int main(void)

需要注意的是凡巨集定義裡有用'#'或'##'的地方巨集引數是不會再展開的。

#define a (2)

#define str(s) br##define cons(a,b) int(a##e##b)

printf("int max: %s\n", str(int_max));

這行會被展開為:

printf("int max: %s\n", "int_max");

printf("%s\n", cons(a, a));

這一行被展開為:

printf("%s\n", int(aea));

int_max和a都不會再被展開, 然而解決這個問題的方法很簡單,多加一層中間轉換巨集。加這層巨集的用意是把所有巨集的引數在這層裡全部展開,那麼在轉換巨集裡的那乙個巨集(_str)就能得到正確的巨集引數。

#define a2)

#define _str(s) br##define str(s) _str(s轉換巨集

#define _cons(a,b) int(a##e##b)

#define cons(a,b) _cons(a,b) // 轉換巨集

printf("int max: %s\n", str(int_max));

輸出為:int max: 0x7fffffff

str(int_max) --> _str(0x7fffffff) --> "0x7fffffff"

printf("%d\n", cons(a, a));

輸出為:200

cons(a, a) --> _cons((2), (2)) --> int((2)e(2))

以下為minix3作業系統相關的源**:

#ifdef _ansi

#define __str(x) # x

#define __xstr(x) __str(x轉換巨集

_prototype( void __bad_assertion, (const char *_mess) );

#define assert(expr)((expr)? (void)0 : \

bad_assertion("assertion \"" #expr \

failed, file " __xstr(__file__) \

line " __xstr(__line__) "\n"))

#define ___anonymous1(type, var, line) type var##line

#define __anonymous0(type, lineanonymous1(type, _anonymous, line)

#define anonymous(typeanonymous0(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__在第二層才能被解開;

#define fill(a)

enum idd;

typedef struct msg

msg;

msg _msg = ;

相當於:

msg _msg = , };

#define _get_file_name(f) #f

#define get_file_name(f) _get_file_name(f) // 轉換巨集

static char file_name = get_file_name(__file__);

#define _type_buf_size(type) sizeof #type

#define type_buf_size(type) _type_buf_size(type)

char buf[type_buf_size(int_max)];

--> char buf[_type_buf_size(0x7fffffff)];

--> char buf[sizeof "0x7fffffff"];

這裡相當於:

char buf[11];

編寫**的過程中,經常會輸出一些除錯資訊到螢幕上,一般會呼叫printf這類的函式。

但是當除錯解決之後,我們需要手工將這些地方刪除或者注釋掉。

再這次的專案中就用到類似問題,為了除錯程式,再一些地方輸出了很多的資訊,隨著專案的除錯,輸出的資訊越來越多。於是就面臨著,如何處理這些輸出資訊的語句。

簡單刪掉,不僅有一定的工作量,而且也不能保證之後就不出現問題,出現問題後這些資訊還是有用的。

不去掉,帶著除錯資訊就上線,這是明顯不允許的。

於是就想到了乙個可行的辦法。如下:

void myprintf(char* fmt, ...)

#ifdef debug

#define printf(fmt, args...) myprintf(fmt, ##args)

#endif

除錯階段帶著debug除錯,正式上線就可以把printf變成乙個空函式了。

這樣做的乙個潛在風險是可能會導致默寫glib函式需要呼叫printf輸出錯誤log也給取消掉了。

令人欣慰的是,大部分glib呼叫的應該是fprintf。

雖然問題解決了,但是我對args...以及##args還是不太了解。上網找了些gcc手冊的資料如下:

帶有可變引數的巨集(macros with a variable number of arguments)

IO,IOR,IOW,IOWR巨集的用法與解析

io,ior,iow,iowr巨集的用法與解析.txt41滴水能穿石,只因為它永遠打擊同一點。42火柴如果躲避燃燒的痛苦,它的一生都將黯淡無光。巨集 io,ior,iow,iowr 巨集的用法與解析 2010 10 26 11 27 10 標籤 it 分類 人生 在驅動程式裡,ioctl 函式上傳送...

C語言函式和巨集定義

一 目的和要求 1 掌握函式的定義方法和呼叫規則。2 掌握c語言程式中主調函式和被呼叫函式之間進行資料傳遞的規則。3 了解函式的返回值及它的型別,並正確使用它。4 了解區域性變數和全域性變數的作用域及它們與儲存分類的關係,理解變數的存在性和可見性的概念。5 練習遞迴函式的使用。6 理解巨集的概念,掌...

全域性變數巨集定義 精

以下是如何定義全域性變數。眾所周知,全域性變數應該是得到記憶體分配且可以被其他模組通過c語言中extern關鍵字呼叫的變數。因此,必須在 c 和 h 檔案中定義。這種重複的定義很容易導致錯誤。error e46 undefined external serbfr referred in zlg522...