如何在全局范围内定义预处理器变量?

4
我是一名有用的助手,可以为您翻译文本。
我正在使用C++编写Arduino草图。 我希望用户能够在sketch.ino文件中直接定义常量#define,这将需要编译代码。 Arduino IDE使用g ++编译器。
假设我们有三个文件:
sketch.ino
sketch.h
sketch.cpp

在 sketch.h 中,我定义了:
#define OPTION_1 0
#define OPTION_2 1
#define OPTION_3 2
#define OPTION_4 3
#define SLOW 0
#define FAST 1

在sketch.ino中,用户定义了MYOPTION:
#define MYOPTION OPTION_2

在sketch.h中,我使用变量来定义宏:
#if MYOPTION == OPTION_1 | MYOPTION == OPTION_2
    #define SPEED FAST
#else
    #define SPEED SLOW
#endif

在 sketch.cpp 中,我使用它来改进时间关键代码:
MyClass::foo() {
    // do something
    #if SPEED == FAST
    // do more
    #if MYOPTION == OPTION_2
    // do something extra
    #endif
    #endif
    #if MYOPTION == OPTION_4
    // do something else
    #endif
    }

不幸的是,在sketch.cpp文件中似乎无法识别MYOPTION的定义。然而,sketch.cpp可以识别在sketch.h中定义的变量。是否有一种方法可以全局定义预处理器变量,以便在使用它们的任何文件中都可以访问它们?


1
你所使用的 g++ 编译器优化能力如何?您可能希望绕过所有这些预处理程序垃圾,让编译器来处理它,因为使用带有 enum 的标准 if 可以做到同样的效果,而且更加简洁。通常最好优先使用 const 而不是 #define - tadman
@tadman 预处理器不可能优化我的代码。该代码是根据附加的硬件定制的。用户提供的选项决定了哪些时间关键函数部分需要用于该硬件。由于(在这种情况下)Arduino Due的内存限制,提供多个函数是没有意义的。 - uzumaki
MYOPTION的那个定义看起来有点可疑,带有等号。 - Robert Prévost
我的意思是,任何优化编译器都会删除if(false)块内的代码。如果该块内的代码在某些平台上无法编译,则确实只需要实际的#ifdef类型块。 - tadman
让这个程序正常工作需要预处理器按照正确的顺序能够看到所有宏定义。这意味着sketch.cpp需要包含sketch.h,而sketch.h需要在MY_OPTION_2等定义之后、#if之前包含sketch.ino文件。 - Peter
显示剩余2条评论
1个回答

3
将选项定义移动到单独的文件中,例如options.h。您也可以在sketch.ino中定义它们。
在sketch.ino和sketch.h中包含options.h。
将所有依赖于MYOPTION宏的代码从sketch.cpp移动到sketch.h。
在包含sketch.h之前,在sketch.ino中定义MYOPTION。
#include "options.h"
#define MYOPTION OPTION_2
#include "sketch.h"

这是一个使用这种技术的流行库的示例:

https://github.com/PaulStoffregen/Encoder

它允许用户通过ENCODER_DO_NOT_USE_INTERRUPTSENCODER_OPTIMIZE_INTERRUPTS宏来配置从草稿中使用中断的方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接