在 Arduino 的#if #else #endif 中定义变量 IDE
Defining variables within #if #else #endif in Arduino IDE
我希望有人能阐明为什么这段代码不能在 Arduino IDE(使用 1.0.5)中编译。以下代码仅在 DEBUG=1 时编译,但在设置为 0 时不编译。
我希望实现的只是一种简单的方法,在我交换 LED 驱动器时使用相同的代码,并在重新编译和上传之前翻转 DEBUG 位。
注意:此示例是IDE中要编译的全部代码(不需要其他代码)。
问题代码:
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
#if DEBUG == 1
int x = 123;
//Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
int x = 567;
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
错误:
core.a(main.cpp.o): In function `main':
C:\arduino\hardware\arduino\cores\arduino/main.cpp:11: undefined reference to `setup'
C:\arduino\hardware\arduino\cores\arduino/main.cpp:14: undefined reference to `loop'
原因是 Arduino IDE 很烂。在引擎盖下,它会像这样生成 C 代码
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
#if DEBUG == 1
int x = 123;
//Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
int x = 567;
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
因此,如果 debug==0,编译器将看不到生成的函数原型。只需将编译器输出设置为详细,然后在构建目录中查看生成的代码。
所有这些痛苦的解决方案是找到一些方法来阻止 IDE 来扰乱你的东西。过去我在函数原型方面遇到了一些类似的问题,我用 TRICK17 宏解决了这些问题(有关详细信息,请参阅 here)。我不会深入讨论这个宏的混乱实现,因为现在我找到了一个明显更好的解决方案。
- IDE 不知道命名空间
- 因此它不会触及名称空间内的任何内容
- 允许一个空的命名空间名称,这将建立一个匿名命名空间。此命名空间中的实体不需要前缀来寻址它们。
因此新的解决方案是
namespace {
// name of namespace left empty --> this is the anonymous namespace
// now the IDE will not mess with our stuff
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
#if DEBUG == 1
int x = 123;
//Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
int x = 567;
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
}
void setup() { }
void loop() { }
好的!在 Udo 的帮助下弄明白了。
发生了什么:
当 Arduino IDE 编译时,它会自动为 *.ino 文件中的所有函数创建所有头文件声明。我假设当它这样做时,它必须在遇到的第一个变量上触发。但是,如果您按照我的方式进行操作,并且在代码中的 第一个变量 上使用 #if,#else 指令并省略它,那么它将无法为循环创建所有正确的声明, setup, foo, bar() 等。如果第一个变量是 "visible",它会正确创建所有内容。
解决方法:
在#if,#else 之前的代码顶部创建一个无意义的变量。
正在运行的示例:
byte nonsense_var = 0; //this line solves everything!
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 works now!
#if DEBUG == 1
Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
也只需要一个分号就可以了(而不是完整的 var 声明)
; //this line ALSO solves everything!
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 works now!
#if DEBUG == 1
Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
我希望有人能阐明为什么这段代码不能在 Arduino IDE(使用 1.0.5)中编译。以下代码仅在 DEBUG=1 时编译,但在设置为 0 时不编译。
我希望实现的只是一种简单的方法,在我交换 LED 驱动器时使用相同的代码,并在重新编译和上传之前翻转 DEBUG 位。
注意:此示例是IDE中要编译的全部代码(不需要其他代码)。
问题代码:
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
#if DEBUG == 1
int x = 123;
//Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
int x = 567;
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
错误:
core.a(main.cpp.o): In function `main':
C:\arduino\hardware\arduino\cores\arduino/main.cpp:11: undefined reference to `setup'
C:\arduino\hardware\arduino\cores\arduino/main.cpp:14: undefined reference to `loop'
原因是 Arduino IDE 很烂。在引擎盖下,它会像这样生成 C 代码
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
#if DEBUG == 1
int x = 123;
//Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
int x = 567;
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
因此,如果 debug==0,编译器将看不到生成的函数原型。只需将编译器输出设置为详细,然后在构建目录中查看生成的代码。
所有这些痛苦的解决方案是找到一些方法来阻止 IDE 来扰乱你的东西。过去我在函数原型方面遇到了一些类似的问题,我用 TRICK17 宏解决了这些问题(有关详细信息,请参阅 here)。我不会深入讨论这个宏的混乱实现,因为现在我找到了一个明显更好的解决方案。
- IDE 不知道命名空间
- 因此它不会触及名称空间内的任何内容
- 允许一个空的命名空间名称,这将建立一个匿名命名空间。此命名空间中的实体不需要前缀来寻址它们。
因此新的解决方案是
namespace {
// name of namespace left empty --> this is the anonymous namespace
// now the IDE will not mess with our stuff
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 causes compiler error
#if DEBUG == 1
int x = 123;
//Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
int x = 567;
//Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
}
void setup() { }
void loop() { }
好的!在 Udo 的帮助下弄明白了。
发生了什么: 当 Arduino IDE 编译时,它会自动为 *.ino 文件中的所有函数创建所有头文件声明。我假设当它这样做时,它必须在遇到的第一个变量上触发。但是,如果您按照我的方式进行操作,并且在代码中的 第一个变量 上使用 #if,#else 指令并省略它,那么它将无法为循环创建所有正确的声明, setup, foo, bar() 等。如果第一个变量是 "visible",它会正确创建所有内容。
解决方法: 在#if,#else 之前的代码顶部创建一个无意义的变量。
正在运行的示例:
byte nonsense_var = 0; //this line solves everything!
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 works now!
#if DEBUG == 1
Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }
也只需要一个分号就可以了(而不是完整的 var 声明)
; //this line ALSO solves everything!
#define DEBUG 0 //DEBUG=1 works, DEBUG=0 works now!
#if DEBUG == 1
Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
#else
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();
#endif
void setup() { }
void loop() { }