CPP宏:提供实例化/调用次数的计数器 [英] CPP Macro: Counter that gives number of instantiations/calls

查看:108
本文介绍了CPP宏:提供实例化/调用次数的计数器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想拥有一个 C 预处理器宏,到目前为止,该宏知道该宏的实例化/宏调用的数量。
示例:

I want to have a C preprocessor macro that knows the number of instantiations/macro calls of this macro so far. Example:

int main() {
  printf("%d\n", MACRO());
  printf("%d\n", MACRO());
}

应打印

0
1

类似这样的可能?

请注意,将其转发给以下建议的功能还不够。
它应在以下环境下工作:

Note that it is not enough to forward this to a function as proposed below. It should work in the following context:

// global variable
std::vector<bool> calls_hit;

#define OTHER_MACRO() \
{ \
    const int counter = MACRO(); \
    calls_hit.resize(std::max(calls_hit.size(), counter)); \
    calls_hit[counter] = true; \
}


推荐答案

我碰巧有一种与 __ COUNTER __ 类似(使用)的解决方案,但不仅限于单个计数器-您可以根据需要定义多个计数器。

I happen to have a solution that is similar (in usage) to __COUNTER__ , but is not limited to single counter - you can define many counters as you like.

此功能使用了gcc特有的功能,但应该可以在其他工具链中执行类似的操作。

This one uses gcc-specific feature, but should be able to do similar in other toolchain.

static int getpos(int lineno); // forward declaration

#define MY_COUNTER ({                                                    \
            static const int mark __attribute__((LSEG,used)) = __LINE__; \
            getpos(__LINE__);                                            \
})

static int __attribute__((noinline)) getpos(int lineno) {
    static const int mark __attribute__((LSEG,used)) = __LINE__;
    const int *p = &mark;
    int i;
    for (i = 0; *p++ != lineno; i++);
    return i;
}

在上面的代码中,LSEG扩展为section(。rodata.line01234 )是根据 __ LINE __ 信息生成的。

In above code, LSEG expands to something like section(".rodata.line01234") generated from __LINE__ information.

以下是其工作原理的说明:

Here's an expalanation of how this works:


  1. 每当您使用MY_COUNTER宏时,它将被2个代码片段代替:1)将 __ LINE __ 值压入的代码LSEG宏指定的内存段,以及2)调用getpos( __ LINE __ )函数的代码,该函数返回写入给定行的调用数。

  2. LSEG宏扩展到具有行号的段说明符(例如:section(。rodata.line01234))。

  3. 通过指定链接器以字母顺序对段进行排序(-Wl, --sort-segment = name与GNU ld),可以确保所有附加的 __ LINE __ 值均按使用顺序排列。

  4. 在运行时,getpos( __ LINE __ )函数扫描内存段,并返回写到给定行的调用数。

  1. Whenever you use MY_COUNTER macro, it is replaced with 2 code fragments: 1) code that pushes __LINE__ value to memory segment specified by LSEG macro, and 2) code that calls getpos(__LINE__) function, which returns # of calls written up to given line.
  2. LSEG macro expands to section specifier with a line number (ex: section(".rodata.line01234")).
  3. By specifying linker to sort segment alphabetically (-Wl,--sort-segment=name with GNU ld), you can be sure all appended __LINE__ values are in order they were used.
  4. At run-time, getpos(__LINE__) function scans through the memory segment, and returns # of calls written up to given line.

希望这会有所帮助。

这篇关于CPP宏:提供实例化/调用次数的计数器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆