当前位置: 首页 > 知识库问答 >
问题:

c++ - C++的这些宏怎么理解?

江飞白
2024-08-27

C++的这些宏怎么理解
下面代码出自:https://github.com/sharkdp/dbg-macro的dbg.h头文件中

#define DBG_IDENTITY(x) x
#define DBG_CALL(fn, args) DBG_IDENTITY(fn args)

#define DBG_CAT_IMPL(_1, _2) _1##_2
#define DBG_CAT(_1, _2) DBG_CAT_IMPL(_1, _2)

#define DBG_16TH_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
                      _14, _15, _16, ...)                                     \
  _16
#define DBG_16TH(args) DBG_CALL(DBG_16TH_IMPL, args)
#define DBG_NARG(...) \
  DBG_16TH((__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))

// DBG_VARIADIC_CALL(fn, data, e1, e2, ...) => fn_N(data, (e1, e2, ...))
#define DBG_VARIADIC_CALL(fn, data, ...) \
  DBG_CAT(fn##_, DBG_NARG(__VA_ARGS__))(data, (__VA_ARGS__))

// (e1, e2, e3, ...) => e1
#define DBG_HEAD_IMPL(_1, ...) _1
#define DBG_HEAD(args) DBG_CALL(DBG_HEAD_IMPL, args)

// (e1, e2, e3, ...) => (e2, e3, ...)
#define DBG_TAIL_IMPL(_1, ...) (__VA_ARGS__)
#define DBG_TAIL(args) DBG_CALL(DBG_TAIL_IMPL, args)

#define DBG_MAP_1(fn, args) DBG_CALL(fn, args)
#define DBG_MAP_2(fn, args) fn(DBG_HEAD(args)), DBG_MAP_1(fn, DBG_TAIL(args))
#define DBG_MAP_3(fn, args) fn(DBG_HEAD(args)), DBG_MAP_2(fn, DBG_TAIL(args))
#define DBG_MAP_4(fn, args) fn(DBG_HEAD(args)), DBG_MAP_3(fn, DBG_TAIL(args))
#define DBG_MAP_5(fn, args) fn(DBG_HEAD(args)), DBG_MAP_4(fn, DBG_TAIL(args))
#define DBG_MAP_6(fn, args) fn(DBG_HEAD(args)), DBG_MAP_5(fn, DBG_TAIL(args))
#define DBG_MAP_7(fn, args) fn(DBG_HEAD(args)), DBG_MAP_6(fn, DBG_TAIL(args))
#define DBG_MAP_8(fn, args) fn(DBG_HEAD(args)), DBG_MAP_7(fn, DBG_TAIL(args))
#define DBG_MAP_9(fn, args) fn(DBG_HEAD(args)), DBG_MAP_8(fn, DBG_TAIL(args))
#define DBG_MAP_10(fn, args) fn(DBG_HEAD(args)), DBG_MAP_9(fn, DBG_TAIL(args))
#define DBG_MAP_11(fn, args) fn(DBG_HEAD(args)), DBG_MAP_10(fn, DBG_TAIL(args))
#define DBG_MAP_12(fn, args) fn(DBG_HEAD(args)), DBG_MAP_11(fn, DBG_TAIL(args))
#define DBG_MAP_13(fn, args) fn(DBG_HEAD(args)), DBG_MAP_12(fn, DBG_TAIL(args))
#define DBG_MAP_14(fn, args) fn(DBG_HEAD(args)), DBG_MAP_13(fn, DBG_TAIL(args))
#define DBG_MAP_15(fn, args) fn(DBG_HEAD(args)), DBG_MAP_14(fn, DBG_TAIL(args))
#define DBG_MAP_16(fn, args) fn(DBG_HEAD(args)), DBG_MAP_15(fn, DBG_TAIL(args))

// DBG_MAP(fn, e1, e2, e3, ...) => fn(e1), fn(e2), fn(e3), ...
#define DBG_MAP(fn, ...) DBG_VARIADIC_CALL(DBG_MAP, fn, __VA_ARGS__)

#define DBG_STRINGIFY_IMPL(x) #x
#define DBG_STRINGIFY(x) DBG_STRINGIFY_IMPL(x)

我尝试用渐进的方式去理解,尝试如下代码去理解前两行宏

#define DBG_IDENTITY(x) x
#define DBG_CALL(fn, args) DBG_IDENTITY(fn args)

void test(int x)
{
    std::cout << x << std::endl;
}
int main()
{
    DBG_CALL(test,2);
}

发现代码不可编译,故尝试问之

共有1个答案

柳经纶
2024-08-27

先说结论:改成 DBG_CALL(test, (2)); 可以通过了。

宏替换过程

DBG_CALL(test, (2));
    --> DBG_IDENTITY(test (2));
        --> test(2);

问题来了,为什么不直接写#define DBG_CALL(fn, args) fn(args)? 因为某些情况微软的编译器无法正常处理。比如 arg 是 1,2,3 这种形式,具体可参考 github 代码注释里的连接。

 类似资料:
  • 如果我把 nums 设置为 10000,那么每次都准确输出 20000。或者设置的值比 10000 要少时也能准确输出。如果我把 nums 设置为 100000,那么每次输出的值都好像是随机的,范围在 100000 到 200000 之间。 如果是因为线程之间执行顺序的问题导致输出不确定,那为什么当值为 10000 时输出的值是比较确定的?

  • 我只是很好奇,在C/C++中你把叫做什么? 例如,。它叫“hashtag if”吗?

  • 软件是 VScode 我尝试使用shift+enter之类的都不行。 这个有 一个 比较详细的术语,或者视频,使用文档吗? (因为我不想换个语言或者编译器就还得重新提问,求告知 换成visual stdio就方 按什么键?

  • #define 叫做 宏定义命令,它也是C语言预处理命令的一种。所谓 宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。 我们先通过一个例子来看一下 #define 的用法: 运行结果: 120 注意第 6 行代码 , 被 代替了。 就是宏定义, 为宏名, 是宏的内容(宏所表示的字符串)。在预处理阶段,对程序中所有出现的“宏名”,预处理器都会

  • 我需要在向量中找到max元素,所以我使用了,但我发现它是一个非常慢的函数,所以我编写了自己的版本,并设法获得更好的x3性能,下面是代码: 输出: 平均而言,要比多花费x3个时间。那么为什么我能够这么容易地创建一个更快的std函数呢?既然std这么慢,我是不是应该停止使用std并编写自己的函数呢? 注意:一开始我以为这是因为我在for循环中使用了andinteger而不是迭代器,但现在看来这并不重要

  • Visual studio是怎么调用外部编译程序CL、链接程序LINK的,unity是怎么调用visual studio的,这种一个程序调用另一个程序是否存在效率问题,和进程间通信是一码事吗

  • 人们似乎在说malloc在使用数组时有多棒,当你不知道一个数组在编译时有多少元素时,你可以使用它(?)。没有malloc你就不能这么做吗?例如,如果我们知道一个字符串的最大长度为10,那么下面的结果是否足够接近同一事物?。。。除了能够释放内存之外。 和

  • 问题内容: 宏非常有用。 因此,我偶尔会抱怨Java和C#中缺少宏。宏允许我强制内联,但允许我对非宏代码进行代码管理。 是否有任何基于Java或C#的项目/产品有效地允许宏或指定行内扩展。 我在想类似的东西 @macro public void hello(int x){…} 或当我调用方法时,调用之前的@inline注释将使被调用方法内联。 或者,我是否应该知道我应该相信编译器为我做出最好的决定