宏中的静态变量

时间:2016-07-06 19:38:18

标签: c++ macros c-preprocessor

我正在查看一些代码并认为整个逻辑在这里没有意义。拥有像这样的宏似乎很差。 作为一个例子,我使用这个宏两次,我得到两个字符串输出。

TESTING("hello");
TESTING("world");
  1. 预处理器只是用代码块替换标识符,它与复制/粘贴代码相同,因此编译器不应该为firstPass提供重新定义错误,如果多次使用此宏? (如果多次手动粘贴mainstatic bool firstPass = true;,编译器将发出错误。)

  2. 如果firstPassstatic,则仅创建并初始化一次。因此,多次使用此宏,不应该产生任何结果(除了第一次使用之外),因为标志设置为false,但每次都会cout

  3. 有点困惑。

    #define TESTING(input)                           \
    {                                                \
       static bool firstPass = true;                 \
       if (firstPass) {                              \
         std::cout << input;                         \
         firstPass = false;                          \
       }                                             \
    }
    

1 个答案:

答案 0 :(得分:5)

此宏无法按预期工作。编译器允许它的原因的关键是{ }周围的static bool firstPass。这会创建一个新的范围,允许新变量通过该名称隐藏任何其他变量。当该范围结束时,静态不再可见。

由于新的范围,这是合法的:

void f()
{
    int i = 0;
    {
        int i = 1;
        {
            int i = 2;
        }
    }
}

通过将firstPass移出宏来实现它的预期方式。

static bool firstPass = true;
#define TESTING(input)                           \
{                                                \
   if (firstPass) {                              \
     std::cout << input;                         \
     firstPass = false;                          \
   }                                             \
}

ETA :或者它可能按预期工作。使用宏中的静态bool,每个调用站点将只打印一次输出,因为每个调用站点都有自己的firstPass标志实例。使用宏外部的静态布尔只有第一个要到达的呼叫站点将报告它的输出,并且只在第一次到达时报告。

因此宏中的静态bool

f()
{
    for ( int i = 0; i < 1000; ++i )
    {
         TESTING( "A\n" );
         TESTING( "B\n" );
         TESTING( "C\n" );
    }
}

int main()
{
    for ( int i = 0; i < 5; ++i ) 
        f();
    return 0;
}

将打印

A
B
C

但是宏外部的静态bool只会打印

A