使用 c/c++ 宏禁用多行语句
Disable multiline statements with c/c++ macro
是否可以根据某些定义使用 c/c++ 预处理器禁用代码块,而不用 #ifdef #endif
检测代码?
// if ENABLE_TEST_SONAR is not defined, test code will be eliminated by preprocessor
TEST_BEGIN(SONAR)
uint8_t sonar_range = get_sonar_measurement(i);
TEST_ASSERT(sonar_range < 300)
TEST_ASSERT(sonar_range > 100)
TEST_END
功能等同于以下内容:
#ifdef TEST_SONAR
serial_print("test_case sonar:\r\n");
uint8_t sonar_range = get_sonar_measurement(i);
serial_print(" test sonar_range < 300:%d\r\n", sonar_range < 300);
serial_print(" test sonar_range > 100:%d\r\n", sonar_range > 100);
#endif TEST_SONAR
不,使用预处理有效禁用部分代码的唯一方法是#ifdef #endif
。理论上,您可以使用 #if identifier
,但最好坚持检查变量是否已定义。
另一种选择(可能)是使用预处理宏:
编辑:
也许使用普通函数 #ifdef
可能会更好?
function test_function() {
/* Do whatever test */
}
#define TESTING_IDENTIFIER
#define TEST( i, f ) if ((i)) do { f } while (0)
然后,对于每个测试,您定义一个唯一标识符并通过首先提供标识符然后提供函数(带括号)来调用它。
TEST( TESTING_IDENTIFIER, test_function() );
最后,f
可以是语法正确的任何东西 -- 您不必为每个测试都创建一个函数,您可以将代码内联。
只能使用 #ifdef
或 #if
禁用多行,但可以使用宏禁用单行。注意多行可以用\
组合
#ifdef DOIT
#define MYMACRO(x) \
some code \
more code \
even more \
#else
#define MYMACRO(x)
#endif
然后当您调用 MYMACRO
时,根据是否定义了 DOIT
,将包含或不包含该代码
这是最接近的,经常用于调试代码
编辑:一时兴起,我尝试了以下方法,它似乎有效(在 MSVC++ 和 g++ 中):
#define DOIT
#ifdef DOIT
#define MYMACRO(x) x
#else
#define MYMACRO(x)
#endif
void foo(int, int, int)
{
}
int main(int, char **)
{
int x = 7;
MYMACRO(
if (x)
return 27;
for (int i = 0; i < 10; ++i)
foo(1, 2, 3);
)
}
无论如何我都会提到一个明显的解决方案
#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
...
TEST_SONAR
code
TEST_SONAR_END
代码仍然会被编译,不会被完全删除,但一些聪明的编译器可能会优化它。
UPD:刚刚测试
#include <iostream>
using namespace std;
//#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
int main() {
TEST_SONAR
cout << "abc" << endl;
TEST_SONAR_END
}
生成完全相同的二进制文件,其中 cout
行被注释掉和未被注释掉,所以代码确实被剥离了。将 g++ 4.9.2 与 -O2
.
一起使用
是否可以根据某些定义使用 c/c++ 预处理器禁用代码块,而不用 #ifdef #endif
检测代码?
// if ENABLE_TEST_SONAR is not defined, test code will be eliminated by preprocessor
TEST_BEGIN(SONAR)
uint8_t sonar_range = get_sonar_measurement(i);
TEST_ASSERT(sonar_range < 300)
TEST_ASSERT(sonar_range > 100)
TEST_END
功能等同于以下内容:
#ifdef TEST_SONAR
serial_print("test_case sonar:\r\n");
uint8_t sonar_range = get_sonar_measurement(i);
serial_print(" test sonar_range < 300:%d\r\n", sonar_range < 300);
serial_print(" test sonar_range > 100:%d\r\n", sonar_range > 100);
#endif TEST_SONAR
不,使用预处理有效禁用部分代码的唯一方法是#ifdef #endif
。理论上,您可以使用 #if identifier
,但最好坚持检查变量是否已定义。
另一种选择(可能)是使用预处理宏:
编辑:
也许使用普通函数 #ifdef
可能会更好?
function test_function() {
/* Do whatever test */
}
#define TESTING_IDENTIFIER
#define TEST( i, f ) if ((i)) do { f } while (0)
然后,对于每个测试,您定义一个唯一标识符并通过首先提供标识符然后提供函数(带括号)来调用它。
TEST( TESTING_IDENTIFIER, test_function() );
最后,f
可以是语法正确的任何东西 -- 您不必为每个测试都创建一个函数,您可以将代码内联。
只能使用 #ifdef
或 #if
禁用多行,但可以使用宏禁用单行。注意多行可以用\
#ifdef DOIT
#define MYMACRO(x) \
some code \
more code \
even more \
#else
#define MYMACRO(x)
#endif
然后当您调用 MYMACRO
时,根据是否定义了 DOIT
这是最接近的,经常用于调试代码
编辑:一时兴起,我尝试了以下方法,它似乎有效(在 MSVC++ 和 g++ 中):
#define DOIT
#ifdef DOIT
#define MYMACRO(x) x
#else
#define MYMACRO(x)
#endif
void foo(int, int, int)
{
}
int main(int, char **)
{
int x = 7;
MYMACRO(
if (x)
return 27;
for (int i = 0; i < 10; ++i)
foo(1, 2, 3);
)
}
无论如何我都会提到一个明显的解决方案
#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
...
TEST_SONAR
code
TEST_SONAR_END
代码仍然会被编译,不会被完全删除,但一些聪明的编译器可能会优化它。
UPD:刚刚测试
#include <iostream>
using namespace std;
//#define DO_TEST_SONAR
#ifdef DO_TEST_SONAR
#define TEST_SONAR if(true) {
#else
#define TEST_SONAR if(false) {
#endif
#define TEST_SONAR_END }
int main() {
TEST_SONAR
cout << "abc" << endl;
TEST_SONAR_END
}
生成完全相同的二进制文件,其中 cout
行被注释掉和未被注释掉,所以代码确实被剥离了。将 g++ 4.9.2 与 -O2
.