来自usbtiny / defs.h(ATTiny控制器的AVR libc USB代码):
#define CAT2(a,b) CAT2EXP(a, b)
#define CAT2EXP(a,b) a ## b
#define CAT3(a,b,c) CAT3EXP(a, b, c)
#define CAT3EXP(a,b,c) a ## b ## c
什么是##运算符?我已经这样做了30年了,我很难过。谷歌并没有帮助,因为我不认为他们会将这些字符编入索引。
答案 0 :(得分:9)
宏定义中的##
符号表示连接。
所以
#define concat(a,b) a ## b
意味着
concat (pri, ntf) ("hello world\n");
后处理
printf("hello world\n");
文档here。
同样有用的是stringify运算符(#
),不应该与此混淆。
测试:
/* test with
* gcc -E test.c
* having removed the #include lines for easier to read output
*/
#include <stdio.h>
#include <stdlib.h>
#define concat(a,b) a ## b
int
main (int argc, char **argv)
{
concat (pri, ntf) ("Hello world\n");
exit (0);
}
为什么额外的间接水平?正如Deduplicator在评论中指出他的答案如下,没有它,它将连接指定的字面术语,而不是宏替换术语。这些陷阱的有用列表是here。
答案 1 :(得分:2)
CAT2
和CAT3
是应该调用的宏,另外两个是内部工作的一部分。
#define CAT2(a,b) CAT2EXP(a, b)
#define CAT2EXP(a,b) a ## b
那么,如果你拨打CAT2
会怎么样?
好吧,首先替换CAT2
,它会扩展文字参数:
CAT2(a_eval, b_eval)
通过##
标记连接运算符将两个参数连接成一个标记来替换它。