强制编译器忽略程序中的某些行

假设我有10,000行C ++代码。 此代码的200行用于testing目的(例如,检查程序并显示错误消息)。

有没有办法在C + +忽略或考虑代码的一些行(可能与预处理关键字)?

简短的回答:

使用macros#ifdef检查。 例如:

 #ifdef MY_CONTROL_MACRO ... #endif 

如果您已经定义了MY_CONTROL_MACROmacros,则仅编译该范围内的代码。


更多东西:

  1. 要定义这样一个macros,你可以

    • #define MY_CONTROL_MACRO添加到您的代码中。 要么,
    • 对于VS,将MY_CONTROL_MACRO添加到Project > Properties > C/C++ > Preprocessor > Preprocessor Definitions 。 要么,
    • 对于GCC,请使用选项-DMY_CONTROL_MACRO编译您的代码。
  2. 你可以在这里查看更多信息。

    这个块被称为条件组。 当且仅当MACRO被定义时,受控文本将被包括在预处理器的输出中。 如果MACRO被定义,条件成功,否则失败。

    条件内的受控文本可以包含预处理指令。 只有条件成功时才执行。 您可以在其他条件组内嵌套条件组,但它们必须完全嵌套。 换句话说,“#endif”总是匹配最接近的#ifdef(或#ifndef或#if)。 另外,您不能在一个文件中启动一个条件组,并在另一个文件中结束它。

  3. 你也可以使用先进的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模式下编译每个其他库。

这是#ifdefdevise目的

你把

 #ifdef TESTS ... test code ... #endif 

然后您可以传递给编译器选项来决定是否要将testing部分编译进去。 例如,用g ++就是了

 g++ -DTESTS ... 

使用现有的约定,并使用NDEBUGmacros。 所有常见的编译器都将这个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呢?

  1. 如果在整个代码中有很多独立的debugging语句,那么读起来会更容易一些
  2. 更重要的是,即使没有生成代码,代码也总是处理语法错误。 如果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