假设我有一万行C++代码,其中两百行是用于测试目的的(例如,检查程序并显示错误消息)。
在C++中是否有一种方法可以忽略或考虑某些代码行(可能使用预处理器关键字)?
使用宏和#ifdef
检查。例如:
#ifdef MY_CONTROL_MACRO
...
#endif
只有在您定义了MY_CONTROL_MACRO
宏之后,此作用域中的代码才会被编译。
要定义这样的宏,您可以:
#define MY_CONTROL_MACRO
添加到您的代码中。或 MY_CONTROL_MACRO
添加到项目 > 属性 > C/C++ > 预处理器 > 预处理器定义
中。或 -DMY_CONTROL_MACRO
编译您的代码。 您可以在此处查看更多信息。
此块称为条件组。仅当定义MACRO时,控制文本才会包含在预处理器的输出中。如果定义了MACRO,则我们说条件成功;否则失败。
条件中的受控文本可以包括预处理指令。仅当条件成功时才执行它们。您可以在其他条件组内嵌套条件组,但它们必须完全嵌套。换句话说,“#endif”始终匹配最近的“#ifdef”(或“#ifndef”或“#if”)。此外,您不能在一个文件中开始条件组并在另一个文件中结束。
您还可以使用高级的ifdef-else-endif
样式:
#ifdef MY_CONTROL_MACRO
... // this part will be valid if MY_CONTROL_MACRO is defined
#else
... // this part will be valid if MY_CONTROL_MACRO is NOT defined
#endif
-D_DEBUG
运行 GCC? - You_DEBUG
“不可移植”? - YouNDEBUG
,在调试版本中未定义。特别地,定义它会移除assert
评估。 - MSalters#if ONLY_FOR_DEBUG
,而不是#ifdef
。 - Ben Voigt在代码周围加上"#ifdef...#endif",然后使用编译器选项来设置标志:
#ifdef MYTEST_ONLY_FUNCTIONALITY_ENABLED
...
#endif
您可以使用编译器选项来包含这段代码。例如,在GCC中:-DMYTEST_ONLY_FUNCTIONALITY_ENABLED
说实话,我认为这种方法在大型项目中通常不太可维护,如果可能的话,通常最好将仅用于测试的代码移至完全独立的库中(没有这种条件逻辑),并将该代码链接到测试二进制文件而不是非测试二进制文件中。这也避免了需要同时编译每个其他库的调试模式和非调试模式。
#ifdef
的设计初衷。#ifdef TESTS
... test code ...
#endif
然后你可以传递编译器选项来决定是否编译测试部分。例如,使用g++:
g++ -DTESTS ...
#if
的设计目的。#ifdef
的设计目的是提供默认值,例如#ifndef VALUE
/ #define VALUE DEFAULT_VALUE
/ #endif
。 - Ben Voigt使用预处理器保护是最灵活和常见的方法。但是,在可能的情况下,我建议使用if语句。例如,不要使用以下代码:
void example(int a){
int some_local;
...
#ifdef _DEBUG
std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl;
#endif
....
}
void example(int a){
int some_local;
...
if(ENABLE_DEBUG) std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl;
...
}
由于ENABLE_DEBUG是一个常量,当ENABLE_DEBUG为0时,编译器将不会为其保护的语句生成任何代码。那么,为什么要使用这种方法而不是#ifdef?
显然,此方法仅适用于方法/函数体内的调试语句。
按照现有惯例,使用NDEBUG
宏。所有常见的编译器都为发布版定义了此宏,并且未为调试版本定义此宏。
该宏最初存在是用于控制assert(3)
的输出,并且自 POSIX标准以来至少从C89开始就定义了该宏。
请注意,您必须使用#ifndef
反转测试。
一个例子:
#ifndef NDEBUG
/* Debugging code */
std::cerr << "So far we have seen " << unicorns << " unicorns" << std::endl;
#endif
附言:使用gcc
/g++
,您可以通过在命令行中添加-g
来进行调试构建。
#define MY_VARIABLE
并按以下方式使用
#ifdef MY_VARIABLE
//code that compiles only if MY_VARIABLE is defined
printf("test output here");
#else
//code that compiles only if MY_VARIABLE is NOT defined
printf("MY_VARIABLE is not defined");
#endif
欲了解更多信息,请在网上搜索
#define, #if, #ifdef, #ifndef
使用预处理器指令,将define
传递给编译器或从头文件"config.h"中获取是正确的方法:
#if defined(DEBUG) // or #ifdef DEBUG
// Debug code
#endif
#if defined(DEBUG)
My_Debug_function(some_variable)
#endif
#if !defined(DEBUG) // or #ifndef DEBUG
# define My_Debug_function(some_variable) do { static_cast<void>(some_variable); } while (false) /* Do nothing */
#endif
因此,几乎可以正常使用My_Debug_function
。
在你的测试代码中加上#ifdef DEBUG
。
#if DEBUG
....
#endif
#ifdef TESTS
被称为条件编译。 - Grijesh Chauhan#ifdef
(或#if defined
)。那是一种糟糕的风格,几乎完全错误。应该使用#if
而不是#ifdef
。原因是#define IS_TEST_BUILD 0
应该与#undef IS_TEST_BUILD
产生相同的效果,而不是与#define IS_TEST_BUILD 1
产生相同的效果。 - Ben Voigt