C中的##运算符

mic*_*ael 14 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
Run Code Online (Sandbox Code Playgroud)

(除了##部分,我知道它的全部功能.)

Ker*_* SB 15

它是字符串连接,作为预处理器宏的一部分.

(在此上下文中,"string"当然是指预处理程序令牌,或者是"源代码字符串",而不是 C字符串.)


Set*_*gie 11

它被称为粘贴运算符; 它将文本bt与文本连接起来bit.例如,如果您的宏调用是

REGISTER_BIT(x, 4)
Run Code Online (Sandbox Code Playgroud)

它会扩展到

((volatile _io_reg*)&x)->bit4
Run Code Online (Sandbox Code Playgroud)

没有它,你不能直接在宏体中的文本旁边放置一个宏参数,因为那时文本将触及参数名称并成为同一个标记的一部分,并且它将变成一个不同的名称.


Ama*_*wal 6

运算符##连接两个参数,它们之间不留空格:

#define glue(a,b) a ## b
glue(c,out) << "test";
Run Code Online (Sandbox Code Playgroud)


Nat*_*man 3

这是宏定义的一部分。

它允许您在宏内连接字符串。

bt在您的情况下,您可以像这样使用从 7 到 0:

REGISTER_BIT(myreg, 0)
Run Code Online (Sandbox Code Playgroud)

它将被扩展为:

((volatile _io_reg*)&myreg)->bit0

如果没有这个,您必须将bit宏的一部分定义为宏的参数之一:

#define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bt
Run Code Online (Sandbox Code Playgroud)

用法如下:

REGISTER_BIT(myreg, bit0)
Run Code Online (Sandbox Code Playgroud)

这比较麻烦。

这也允许您建立新名称。

假设您有这些宏:

#define AAA_POS 1
#define AAA_MASK (1 << AAA_POS)
#define BBB_POS 2
#define BBB_MASK (1 << BBB_POS)
Run Code Online (Sandbox Code Playgroud)

并且您需要一个从位向量中提取 AAA 的宏。你可以这样写:

#define EXTRACT(bv, field) ((bv & field##_MASK) >> field##_POS)
Run Code Online (Sandbox Code Playgroud)

然后你像这样使用它:

EXTRACT(my_bitvector, AAA)
Run Code Online (Sandbox Code Playgroud)