帮助理解define'ah。
#define QUOTE_(WHAT) #WHAT
#define QUOTE(WHAT) QUOTE_(WHAT)
#define dbg(format, ...) printf("%s: "format, __FILE__":"QUOTE(__LINE__), ## __VA_ARGS__)
#一格和二格有什么区别##?- 如何
QUOTE/工作QOUTE_。为什么一个定义还不够?
帮助理解define'ah。
#define QUOTE_(WHAT) #WHAT
#define QUOTE(WHAT) QUOTE_(WHAT)
#define dbg(format, ...) printf("%s: "format, __FILE__":"QUOTE(__LINE__), ## __VA_ARGS__)
#一格和二格有什么区别##?QUOTE/工作QOUTE_。为什么一个定义还不够?
运营商
#和##根本没有任何关系。因此,“有什么区别”这个问题听起来很奇怪。运算符
#是将宏参数转换为字符串文字的运算符。对于参数,P#P变为"A",其中A是参数对应的参数P。运算符
##是连接运算符,即 将两个单独的相邻宏标记连接成一个标记。在宏处理器中,两个相邻的单个标记仍然是单独的标记,即使它们之间没有空格,除非您明确要求预处理器将它们合并为单个标记##。在宏定义中执行参数替换时,首先检查该宏的每个参数以查看它是否包含对其他宏的引用。如果有,则首先递归地执行在单独参数的框架内对这些宏的替换,并且仅在该过程完成后,将结果插入“在其位置”。
但是(!)如果宏体中的相应参数与or相邻,则不会执行参数内的递归解析和替换过程。
###正是这最后一个细节是宏
QUOTE以这种“两层”方式实现的原因。如果我们只是天真地QUOTE实现那么在这个例子中
宏替换的结果将是一个字符串
"V",但不是一个字符串"vasya"。宏将的值QUOTE作为输入,并且根据上述规则(与 的邻接),不对的值进行任何进一步的分析,而只是立即从中构建一个文字。VWHAT#WHAT"V"如果我们希望宏替换的结果是字符串
"vasya",那么我们需要在某个阶段给宏处理器一个替换为的V机会vasya。为此,这些宏被做成两层首先,宏替换完成
QUOTE(V)。由于在此宏的定义中,参数WHAT不与#或 c中的任何一个相邻##,因此将其替换WHAT为vasya。接下来,我们考虑宏的“调用”QUOTE_(vasya),它将生成我们需要的文字"vasya"。本例中的用法
##不规范,与实际用途无关##。这是 GCC 特有的属性:如果参数为空, ## __VA_ARGS__,逗号将在序列中自动销毁。__VA_ARGS__