c++ 预处理器的应用

在开发2d代码的时候,经常看到一些预处理器的代码,大多是为了调试方便,所以会用预处理器也就比较重要.

1.先看代码

部分取自yushan-base的config.h

1
2
3
4
5
6
7
8
9
#define DEBUG_PAINT_SUCCESS_COURSE
#define DEBUG_PREDICT_OPPONENT_REACH_STEP
#define DEBUG_PREDICT_OPPONENT_REACH_STEP_LEVEL2
#define DEBUG_PREDICT_PLAYER_TURN_CYCLE
#define DEBUG_PREDICT_RECEIVER
#define DEBUG_PRINT
#define DEBUG_PRINT_BALL_UPDATE
#define DEBUG_PRINT_EVALUATE
#define DEBUG_PRINT_FAILED_COURSE

取自action_chain_graph.cpp

1
2
3
4
5
6
7
8
9
#ifdef ACTION_CHAIN_LOAD_DEBUG
std::fprintf( stderr,
"# recursive search: %2d [%ld] % 10lf msec, n=%4lu, average=% 10lf\n",
wm.self().unum(),
wm.time().cycle(),
msec,
n_evaluated,
( n_evaluated == 0 ? 0.0 : msec / n_evaluated ) );
#endif

这样的代码是比较多的,目的是为了debug

2.原理

预处理器确保头文件多次包含仍能安全工作,即可以有效地防止头文件重复包含的发生.
它由c++语言继承c语言而来,预处理器是在编译之前执行的一段程序。
我们比较熟悉的#include 就是一项预处理功能,当预处理器看到#include标记时就会用指定的头文件代替#include。
预处理器还会用到一项预处理功能就是头文件保护符,头文件保护符依赖于预处理变量,而预处理变量有两种状态:已定义和未定义。
我们经常用#define指令把一个名字设定为预处理变量,

#ifdef 和#ifdnf 指令用于 检查某个预处理变量是否已经定义。

#ifdef 为真说明变量已经被定义

#ifndef 为真说明变量还未被定义
一旦上述某个检查结果为真则执行后续操作直至遇到#endif指令为止,
检查结果为假则忽略在其中间的部分。

3.测试实例

  • 定义一个config.h

    1
    #define LOG_TESt
  • main.cpp文件中包含

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream> 
    #include "config.h"
    int main(int argc, char **argv)
    {
    #ifdef LOG_TEST
    std::cout<<"测试有的时候"<<std::endl;
    #endif

    #ifndef LOG_TEST
    std::cout<<"没有的时候"<<std::endl;
    #endif
    return 0;
    }

-测试结果,在config.h里面注释#define LOG_TEST之后,输出的是
‘没有的时候’

4.结论

预处理技术主要功能是防止文件被重复包含,但是在这篇博文中强调的是使用预处理命令来实现对球队代码中输出部分选择编译的功能.
在球队代码中经常可以看到预编译处理的代码.看懂之间的内容,有助于我们进行代码的选择性调试.

忽然想加个彩蛋

5.参考

c预处理器概述