C中的##运算符
##
在C中做什么?
例:
typedef struct { unsigned int bit0:1; unsigned int bit1:1; unsigned int bit2:1; unsigned int bit3:1; unsigned int bit4:1; unsigned int bit5:1; unsigned int bit6:1; unsigned int bit7:1; } _io_reg; #define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt
(除了##部分,我知道它的全部function。)
它是字符串连接 ,作为预处理器宏的一部分。
(在此上下文中,“string”当然是指预处理程序令牌,或“源代码字符串”,而不是 C字符串。)
它被称为粘贴运算符; 它将bt
中的文本与文本bit
。 例如,如果您的宏调用是
REGISTER_BIT(x, 4)
它会扩展到
((volatile _io_reg*)&x)->bit4
没有它,你不能直接在宏体中的文本旁边放置一个宏参数,因为那时文本将触及参数名称并成为同一个标记的一部分,并且它将成为一个不同的名称。
运算符##连接两个参数,它们之间不留空格:
#define glue(a,b) a ## b glue(c,out) << "test";
那是令牌粘贴操作符 。
这是宏定义的一部分。
它允许您在宏内连接字符串。
在你的情况下,你可以像这样使用7到0之间的bt
:
REGISTER_BIT(myreg, 0)
它将扩展为:
((volatile _io_reg*)& myreg )->bit 0
如果没有这个,你必须将宏的bit
部分定义为宏的参数之一:
#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bt
用法是:
REGISTER_BIT(myreg, bit0)
这更麻烦。
这也允许您构建新名称。
假设你有这些宏:
#define AAA_POS 1 #define AAA_MASK (1 << AAA_POS) #define BBB_POS 2 #define BBB_MASK (1 << BBB_POS)
你想要一个从位向量中提取AAA的宏。 你可以像这样写:
#define EXTRACT(bv, field) ((bv & field##_MASK) >> field##_POS)
然后你像这样使用它:
EXTRACT(my_bitvector, AAA)
它不是C构造,它是预处理器function 。 在这种情况下,它的意思是评估bt
变量并将其与bit
前缀连接起来。 如果没有哈希,你会在那里bitbt
它,这显然是行不通的。
以下是来自ffmpeg
的示例, ffmpeg
是一个注册音频和videofilter的宏:
#define REGISTER_FILTER(X, x, y) \ { \ extern AVFilter ff_##y##_##x; \ if (CONFIG_##X##_FILTER) \ avfilter_register(&ff_##y##_##x); \ }
用法可以是:
REGISTER_FILTER(AECHO,aecho,af); REGISTER_FILTER(VFLIP,vflip,vf);