强制编译器忽略程序中的某些行
假设我有10,000行C ++代码。 此代码的200行用于testing目的(例如,检查程序并显示错误消息)。
有没有办法在C + +忽略或考虑代码的一些行(可能与预处理关键字)?
简短的回答:
使用macros和#ifdef
检查。 例如:
#ifdef MY_CONTROL_MACRO ... #endif
如果您已经定义了MY_CONTROL_MACRO
macros,则仅编译该范围内的代码。
更多东西:
-
要定义这样一个macros,你可以
- 将
#define MY_CONTROL_MACRO
添加到您的代码中。 要么, - 对于VS,将
MY_CONTROL_MACRO
添加到Project > Properties > C/C++ > Preprocessor > Preprocessor Definitions
。 要么, - 对于GCC,请使用选项
-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
使用“#ifdef …#endif”环绕代码,然后使用编译器选项设置标志:
#ifdef MYTEST_ONLY_FUNCTIONALITY_ENABLED ... #endif
然后您可以使用编译器选项来包含此代码。 例如,在GCC中:
-DMYTEST_ONLY_FUNCTIONALITY_ENABLED
虽然,说实话,我认为这种方法在大型项目中通常不是很好维护,如果可能的话,简单地把纯粹的testing代码移动到一个完全独立的库(没有这个条件逻辑)代码到您的testing二进制文件而不是您的非testing二进制文件。 这也避免了必须在debugging和非debugging模式下编译每个其他库。
这是#ifdef
devise目的
你把
#ifdef TESTS ... test code ... #endif
然后您可以传递给编译器选项来决定是否要将testing部分编译进去。 例如,用g ++就是了
g++ -DTESTS ...
使用现有的约定,并使用NDEBUG
macros。 所有常见的编译器都将这个macros定义为发布版本,而不是将其定义为debugging版本。
macros原本是为了控制assert(3)
的输出而定义的,并且在POSIX标准中至less从C89开始定义。
请注意,您必须使用#ifndef
来反转testing。
一个例子:
#ifndef NDEBUG /* Debugging code */ std::cerr << "So far we have seen " << unicorns << " unicorns" << std::endl; #endif
PS使用gcc
/ g++
,您可以通过在命令行中添加-g
来执行debugging版本。
使用预处理器后卫无疑是最灵活和最常见的方法。 但是,如果可能的话,我build议使用if语句。 例如,而不是
void example(int a){ int some_local; ... #ifdef _DEBUG std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl; #endif .... }
假设ENABLE_DEBUG定义为0或非零,我会使用
void example(int a){ int some_local; ... if(ENABLE_DEBUG) std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl; ... }
由于ENABLE_DEBUG是一个常量,当ENABLE_DEBUG为0时,编译器将不会为它所保护的语句生成任何代码。 那么,为什么用这个方法代替#ifdef呢?
- 如果在整个代码中有很多独立的debugging语句,那么读起来会更容易一些
- 更重要的是,即使没有生成代码,代码也总是处理语法错误。 如果debugging代码不经常启用,这可能非常有用。 如果variables发生变化(例如,在上面的例子中,如果参数a被重命名),那么进行更改的人将知道他们也必须更新debugging语句。 如果使用了#ifdefs,那么它可以隐藏bit rot,直到有人需要启用debugging代码,然后他们必须去尝试修复代码,这些代码可能不是很明显。
显然这种方法只适用于方法/函数体内的debugging语句。
围绕你的testing代码#ifdef DEBUG
。
#if DEBUG .... #endif
要走的路是使用预处理器指令,将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
。
使用预处理器#define和#if
取决于你的编译器,你应该有一些默认可用的variables,即NDEBUG(用于非debugging)或DEBUG
你可以自己在代码中定义一个variables
#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
在线search更多信息
#define, #if, #ifdef, #ifndef