为什么在一个地方需要双倍英镑,而在这个宏观上不需要其他地方?
Why is the double pound needed in one place but not the others in this macro?
在这个特定的代码中,作者通过使用宏为类 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
相关文章:
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 为什么output_editor Concept不需要output_e迭代器标记
- 在除法中不需要四舍五入
- 与C代码相比,为什么C++代码不需要"#define _POSIX_C_SOURCE 200809L"?
- 将值从另一个数组写入数组,不包括不需要的值 C++
- C++ 写入路径名中包含不需要的空字符的文件
- 是否有必要获取锁并在不需要唤醒线程时通知condition_variable?
- 使用 assimp 加载模型 - 不需要提升?
- 为什么转换函数声明不需要至少一个定义类型说明符
- 返回不需要的值的二叉搜索程序
- 当我不需要数据库中的所有值时,如何部分初始化 c++ 对象?
- C++:用户输入会产生不需要的行为
- 如何在不需要LIBCD.lib的情况下在Visual Studio 6中编译C项目
- 为什么python需要全局关键字而C/C++不需要?
- 将一个宏传递到另一个宏而不是直接传递内容时会出现不需要的额外"空"参数
- 为什么我们需要在 C++ 中检查空指针,而在 Java 中不需要?
- 为什么复制构造函数不需要检查输入对象是否指向自身?
- 为什么不需要在 C++20 中的依赖类型之前指定"typename"?
- 为什么在一个地方需要双倍英镑,而在这个宏观上不需要其他地方?