在这段特殊的代码中,作者通过使用宏为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)
但是,我对宏有些困惑。为什么作者在宏的函数定义部分使用双磅而不是当它被用作递增的类变量时?
编辑:我认为双磅用于连接,但我的困惑来自为什么双磅不是必要的
" CountSeen。什么++"
和
" CountTaken。什么++"
部分。
答案 0 :(得分:1)
双重哈希##
用于连接。因此
INC(_call)
扩展为
VOID inc_call (INT32 taken) { CountSeen. _call ++; if( taken) CountTaken. _call ++;}
请注意,CountSeen. _call ++;
相当于CountSeen._call++;
,但inc _call
不等同于inc_call
。
答案 1 :(得分:1)
让我们看一下第一个宏(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 ++,因为它有两个函数名。
答案 2 :(得分:0)
Double pound只是一种允许在预处理器语法中连接两个术语的语法。
考虑简单的例子:
#define foo(x) foo_##x
void foo_1();
void foo_2();
...
foo(1); // this will call foo_1