将使用"if"的条件放在预处理器C++

Put the condition of using an"if" in preprocessor C++

本文关键字:预处理 处理器 C++ if 条件      更新时间:2023-10-16

我在cpp中写了一段代码。我的代码中有一个循环,必须以指定的频率执行。我希望无论何时选择的频率等于或大于70hz,都有一个"if"语句可以工作,无论何时if的内容在没有"if"的情况下执行,但我不知道如何将其作为预处理器写入。我写了这样的东西,但它总是执行其中的"其他"部分:

    #define Freq70Hz 70
    int frequency = Freq70Hz;
    int main
    { 
        while(true)
        {
            #if frequency == Freq70Hz 
             if(condition ){
             // do the firstthing
             }
            #else 
            // do the firstthing
            #endif
        }
    }

这里混合了静态编译时编程和动态运行时编程。在这种情况下,预处理器如何在编译时知道frequency的值?它可能在程序执行过程中发生变化。你要么想要一个像这样的静态解决方案:

#define FREQUENCY 70 //this can be changed by passing in compiler options
int main()
{ 
    while(true)
    {
#if FREQUENCY > 70
        if(condition ){
            // do the firstthing
        }
#else 
        // do the firstthing
#endif
    }
}

或者你想要一个像这样的动态解决方案:

int frequency = 70;
int main()
{ 
    while(true)
    {
        if(frequency == 70 && condition)
        {
            // do the firstthing
        }
        else
        {
            // do the firstthing
        }
    }
}

您误解了预处理器的作用。

预处理器在程序运行之前进行文本处理

特别是,它只将正常变量视为文本,不知道它们的类型或值在运行时是什么。即使它们是全局变量,如程序启动时初始化的frequency,也是如此我们看到了;预处理器没有。

#define Freq70Hz 70中的别名定义只是文件其余部分的文本替换规则。每当文本("Freq70Hz")出现在程序的其余部分中时,它都会被替换(用"70"代替)——但在编译器看到代码之前。

然后你就成了预处理器规格怪癖的牺牲品。

您认为对#if frequency == Freq70Hz行进行了有意义的评估。您希望变量frequency的值将被考虑在内,我们(但不是预处理器!)知道它是70。但事实并非如此。

预处理器看到预处理器标记frequency。它没有频率是int变量的概念,因为它无法理解C编程语言。它看到这个标记是条件预处理器表达式的一部分。不过,它并没有被告知用一个值来代替它。

现在的问题是:在预处理器条件表达式中执行了所有替换之后,仍然存在的标识符被替换为0(!),参见最新的C草案n1570,6.10.1./4预处理器不会抱怨"未定义的标识符"这使得指令#if frequency == Freq70Hz成为#if 0 == 70,这显然总是错误的。

由于默认使用未定义的预处理器标识符是一个危险的特性——普通编程语言在Basic之后就不再这样做了——所以值得知道很久以前有人向我展示的一个技巧:使用宏函数#define Freq70Hz() 70在功能上是等效的,但当您以后拼写错误时会抱怨。

使用带有模板的死代码消除

template<bool isGE70Hz>
void DoWhile() {
    while(true) {
        if (isGE70Hz) { // dead code elimination as isGE70Hz is compiletime constant.
            if(condition ){
                // do the firstthing
            } 
        } else {
            // do the firstthing
        }
    }
}
int main() {
    if (frequency >= Freq70Hz) // chose specialization
        DoWhile<true>()
    else
        DoWhile<false>()
    // if frequency and Freq70Hz both are compiletime constants you could do
    // DoWhile<frequency >= Freq70Hz>
}

假设// do the firstthing在两者中都是相同的,并且假设frequency在执行中不会更改,我不会使用预处理器。。。如果您使用static const int frequency = Freq70Hz,则稍后执行:

    while(true)
    {
       if(condition || frequency == Freq70Hz){
         // do the firstthing
       }
    }

编译器将根据frequency不会改变的知识编译出合适的东西。也就是说,如果frequency==Freq70Hz,那么整个if部分将不在可执行版本中。如果频率!=频率70Hz,则if部分将只是条件。