C自带的常用的“std::cout”和“printf()”之类作为log输出显然不是一个好的方法,笔者在学习《(C11)深入理解C11:C2011新特性解析与应用》的教程中,抽出如下的代码,在轻量级调试中是一个不错的选择。

  在 C99 标准中,程序员可以使用变长参数的宏定义。变长参数的宏定义是指在宏定义中 参数列表的最后一个参数为省略号,而预定义宏 __VA_ARGS__ 则可以在宏定义的实现部分替换省略号所代表的字符串。比如:

#define PR(...) printf(__VA_ARGS__)

  就可以定义一个 printf 的别名 PR。事实上,变长参数宏与 printf 是一对好搭档。我们可以看如下代码清单所示的一个简单的变长参数宏的应用。

#include <stdio.h>
#define LOG(...) {\
fprintf(stderr,"%s: Line %d:\t", __FILE__, __LINE__);\
fprintf(stderr, __VA_ARGS__);\
fprintf(stderr,"\n");\
}

int main() {
    int x = 3;
    // 一些代码 ...
    LOG("x = %d", x); // 2-1-5.cpp: Line 12: x = 3
}
// 编译选项 :g++ -std=c++11 2-1-5.cpp

  如上代码清单,定义 LOG 宏用于记录代码位置中一些信息。程序员可以根据 stderr 产生的日志追溯到代码中产生这些记录的位置。引入这样的特性,对于轻量级调试,简单的 错误输出都是具有积极意义的。

  注意在使用“#define”进行的宏定义的过程中,换行符是宏定义结束的标志。

  宏定义分为无参数宏定义带参数宏定义两种。

  无参数的宏定义的一般形式为:"#define 标识符 字符序列",比如:

#define PI 3.1415926

  则在定义它们的源程序文件中,凡定义之后出现的单词PI将用3.1415926替代之。

  在宏定义的之前可以有若干个空格、制表符,但不允许有其它字符。宏定义在源程序中单独另起一行,换行符是宏定义的结束标志。如果一个宏定义太长,一行不够时,可采用续行的方法。续行是在键人回车符之前先键入符号"\"。注意回车要紧接在符号"\"之后,中间不能插入其它符号。

  如有必要,宏名可被重复定义。被重复定义后,宏名原先的意义被新意义所代替。

  通常,无参数的宏定义多用于定义常量。程序中统一用宏名表示常量值,便于程序前后统一,不易出错,也便于修改,能提高程序的可读性和可移植性。特别是给数组元素个数一个宏定义,并用宏名定义数组元素个数能部分弥补数组元素个数固定的不足。
  注意:预处理程序在处理宏定义时,只作字符序列的替换工作,不作任何语法的检查。如果宏定义不当,错误要到预处理之后的编译阶段才能发现。宏定义以换行结束,不需要分号等符号作分隔符。

相关文章:《C++数据类型及各种形式的输入输出汇总

致谢

(加)Michael Wong IBM XL编译器中国开发团队《(C11)深入理解C11:C++ 11新特性解析与应用 迷你》

zyc_glboy宏定义\字符串 多行书写时换行