为什么在一个地方需要双倍英镑,而在这个宏观上不需要其他地方?

Why is the double pound needed in one place but not the others in this macro?

本文关键字:宏观 不需要 其他 一个 方需 为什么      更新时间:2023-10-16

在这个特定的代码中,作者通过使用宏为类 COUNTER 的所有成员创建增量函数来做一些聪明的事情。

class COUNTER
{
public:
UINT64 _call;
UINT64 _call_indirect;
UINT64 _return;
UINT64 _syscall;
UINT64 _branch;
UINT64 _branch_indirect;
COUNTER() : _call(0),_call_indirect(0), _return(0), _branch(0), _branch_indirect(0) {}
UINT64 Total()
{
return _call + _call_indirect + _return + _syscall + _branch + _branch_indirect;
}
};
COUNTER CountSeen;
COUNTER CountTaken;
#define INC(what) VOID inc ## what (INT32 taken) { CountSeen. what ++; if( taken) CountTaken. what ++;}
INC(_call)
INC(_call_indirect)
INC(_branch)
INC(_branch_indirect)
INC(_syscall)
INC(_return)

不过,我对宏有点困惑。为什么作者在宏的函数定义部分使用双磅,而不是在将其用作递增的类变量时?

编辑:我知道双磅用于串联,但我的困惑来自为什么双磅在 "伯爵。什么++" 和 "算了。什么++" 部件。

让我们看看第一个宏(INC(_call)(调用扩展到什么:

VOID inc_call (INT32 taken) { CountSeen. _call ++; if( taken) CountTaken. _call ++;}

重新格式化一下,我们得到:

VOID inc_call (INT32 taken) {
CountSeen._call++;
if(taken)
CountTaken._call++;
}

这声明了一个函数,inc_call,它递增CountSeen._call,也可能CountTaken._call。由于变量未调用._call(这是一个无效的标记,因为您不能以句点开头的名称(,因此不应将句点粘附在宏参数上。同样,由于_call++不是有效的令牌(它是两个令牌;您不能在名称中包含加号(,因此那里不应该有井号。

然而,如果没有第一个##,结果将VOID inc _call (INT32 taken)开始,这也是无效的C++因为它有两个函数名。

双哈希##用于串联。因此

INC(_call)

扩展到

VOID inc_call (INT32 taken) { CountSeen. _call ++; if( taken) CountTaken. _call ++;}

请注意,CountSeen. _call ++;等价于CountSeen._call++;,但inc _call不等同于inc_call

双磅只是一种语法,允许在预处理器语法中连接两个术语。

考虑一个简单的例子:

#define foo(x) foo_##x
void foo_1();
void foo_2();
...
foo(1); // this will call foo_1