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

use*_*187 50 c++ preprocessor-directive

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

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

her*_*tao 78

简短回答:

使用#ifdef检查.例如:

#ifdef MY_CONTROL_MACRO
...
#endif
Run Code Online (Sandbox Code Playgroud)

只有在已经定义MY_CONTROL_MACRO宏的情况下,才会编译此范围内的代码.


更多东西:

  1. 要定义这样的宏,您可以

    • 添加#define MY_CONTROL_MACRO到您的代码中.要么,
    • 对于VS,请添加MY_CONTROL_MACROProject > 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
    
    Run Code Online (Sandbox Code Playgroud)

  • @herohuyongtao:怎么样?我假设您可以使用`-D_DEBUG`运行GCC? (3认同)
  • 使用`#if ONLY_FOR_DEBUG`,而不是`#ifdef`. (3认同)

Mic*_*yan 13

用"#ifdef ... #endif"包围代码,然后使用编译器选项设置标志:

#ifdef MYTEST_ONLY_FUNCTIONALITY_ENABLED
...
#endif
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用编译器选项来包含此代码.例如,在GCC中:

-DMYTEST_ONLY_FUNCTIONALITY_ENABLED
Run Code Online (Sandbox Code Playgroud)

虽然,老实说,我认为这种方法在大型项目中通常不易维护,如果可能的话,通常最好只将纯测试代码移动到一个完全独立的库(没有这个条件逻辑)并简单地链接将代码编入测试二进制文件而不是非测试二进制文件.这也避免了在调试和非调试模式下编译每个其他库.

  • 我想说,随着代码量的增加,这种方法简化了可维护性,因为控件仅位于一个位置。当此类构建切换的“数量”增加时,它确实会很快变得无法维护。大约需要 400 个开关才能拥有比宇宙中原子还要多的构建组合(是的,我曾经研究过如此复杂的代码库)!然而,即使这样也比修改注释代码块更容易维护! (2认同)

650*_*502 6

这就是#ifdef为此而设计的

你把

#ifdef TESTS
... test code ...
#endif
Run Code Online (Sandbox Code Playgroud)

然后您可以传递给编译器选项以决定是否要编译测试部分.例如用g ++就可以了

g++ -DTESTS ...
Run Code Online (Sandbox Code Playgroud)


The*_*uke 5

使用预处理器保护绝对是最灵活和最常用的方法。但是,如果可能,我建议使用 if 语句。例如,代替

void example(int a){
   int some_local;
   ...
   #ifdef _DEBUG
   std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl;
   #endif
   ....
}
Run Code Online (Sandbox Code Playgroud)

假设 ENABLE_DEBUG 被定义为 0 或非零,我会使用

void example(int a){
   int some_local;

   ...
   if(ENABLE_DEBUG) std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl;
   ...
}
Run Code Online (Sandbox Code Playgroud)

由于 ENABLE_DEBUG 是一个常量,当 ENABLE_DEBUG 为 0 时,编译器不会为它保护的语句生成任何代码。那么,为什么要使用这种方法而不是#ifdef?

  1. 如果在整个代码中有许多单独的调试语句,它会更容易阅读
  2. 更重要的是,即使没有生成代码,代码也会始终针对语法错误进行处理。如果不经常启用调试代码,这会非常有用。如果变量发生变化(例如,在上面的示例中,如果参数 a 被重命名),那么进行更改的人将知道他们也必须更新调试语句。如果使用#ifdefs,那么它可以隐藏位腐烂,直到有人需要启用调试代码,然后他们必须去尝试修复代码,这对他们来说可能并不明显。

显然,这种方法仅适用于方法/函数体内的调试语句。