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);