【问题标题】:C++ Macros #ifdefC++ 宏 #ifdef
【发布时间】:2020-02-20 21:34:23
【问题描述】:
void testFunc();

int myval = 0;

int main()
{
    int a = 1;

    if (a > 0)
    {
        #define TEST1
        testFunc();
        #undef TEST1
    }

    int b = 2;
    if ( b > 0)
    {
        #define TEST2
        testFunc();
        #undef TEST2
    }

    std::cout << "val : " << myval << endl;

    getchar();

    return 0;
}


void testFunc()
{

#ifdef TEST1
#define HERE 1
#endif

#ifdef TEST2
#define HERE 2
#endif

#ifdef HERE
    myval = HERE;
#else
    myval = -1;
#endif

}

如何在第一次调用 testFunc() 时将 HERE 的值打印为 1,然后在第二次调用时将 HERE 的值打印为 2。

使用我拥有的当前代码,正在打印的值是 -1。

【问题讨论】:

  • 你为什么要为此使用预处理器?看起来你有 XY 问题,你最好描述一下你想要实现的目标
  • 这可能比goto 意大利面条逻辑更糟糕。
  • 我认为 OP 只是想了解预处理器宏,而不是试图解决实际问题。

标签: c++ macros preprocessor


【解决方案1】:

您缺少的是预处理器指令在编译时间之前进行评估。

这意味着当预处理器解析您的代码时:

  1. 设置 TEST1
  2. 取消设置 TEST1
  3. 设置 TEST2
  4. 取消设置 TEST2
  5. 检查 TEST1 是否已定义(未定义)
  6. 检查 TEST2 是否已定义(未定义)
  7. 检查 HERE 是否已定义(未定义)

这意味着testFunc 变为:

void testFunc() {
    myval = -1;
}

然后,在此预处理之后,您的代码将被编译。

我会考虑使用预处理器以外的东西来完成您想要实现的目标。

【讨论】:

    【解决方案2】:

    按照您的意图,这是不可能的。宏是经过评估的before 编译。它将简单地从上到下解析文档并根据宏替换文本。当预处理达到testFunc 时,TEST1TEST2 都不再被定义(你在代码前面的#undef 都是),所以你最终得到了

    void testFunc()
    {
        myval = -1;
    }
    

    然后编译。看起来您想创建类似模板函数的东西?也许actual function templates可以解决你的问题。

    【讨论】:

      【解决方案3】:

      如何在第一次调用 testFunc() 时将 HERE 的值打印为 1,然后在第二次调用时将 HERE 的值打印为 2。

      这是您尝试的函数在预处理后的样子:

      void testFunc()
      {
          myval = -1;
      }
      

      如您所见,该函数不接受任何形式的输入,并且总是无条件地将相同的值赋给全局变量。

      你无法用宏实现你想要的。


      要根据调用函数的次数来打印不同的值,您可以改用函数对象。函数对象可以有内部状态:

      auto testFunc = [HERE = 1]() mutable {
          return HERE++;
      };
      std::cout << testFunc(); // prints 1
      std::cout << testFunc(); // prints 2
      

      【讨论】:

        【解决方案4】:

        所有# 语句都称为预处理器指令。这些是给编译器的指令。您希望实际编译的代码保持一些关于程序运行时的状态。

        您可以通过以下两种方式来实现:

        1. 全局变量
        2. 静态变量

        以下示例显示了这两种方法。每个函数还有一个内存值,它会更新以记住该函数是否被调用过。

        #include <iostream>
        
        bool g_ran_already = false;
        
        int first_different_global()
        {
            if (!g_ran_already)
            {
                g_ran_already = true;
                return 1;
            }
            else
            {
                return 2;
            }
        }
        
        int first_different_static()
        {
            static bool s_ran_already = false;
        
            if(!s_ran_already)
            {
                s_ran_already = true;
                return 1;
            }
            else
            {
                return 2;
            }
        }
        
        int main(int argc, char** argv)
        {
            std::cout << "first_different_global() run 1: " << first_different_global() << "\n";
            std::cout << "first_different_global() run 2: " << first_different_global() << "\n";
            std::cout << "first_different_global() run 3: " << first_different_global() << "\n";
            std::cout << "first_different_static() run 1: " << first_different_static() << "\n";
            std::cout << "first_different_static() run 2: " << first_different_static() << "\n";
            std::cout << "first_different_static() run 3: " << first_different_static() << "\n";
        }
        

        输出:

        first_different_global() run 1: 1
        first_different_global() run 2: 2
        first_different_global() run 3: 2
        first_different_static() run 1: 1
        first_different_static() run 2: 2
        first_different_static() run 3: 2
        

        【讨论】:

          猜你喜欢
          • 2016-03-10
          • 2015-08-18
          • 1970-01-01
          • 1970-01-01
          • 2011-11-06
          • 2010-11-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多