预处理主要有三个方面的内容: 1.宏定义; 2.文件包含; 3.条件编译。 预处理命令以符号“#”开头。
# 空指令,无任何效果
#define 定义宏
#undef 取消已定义的宏
#if 如果给定条件为真,则编译下面代码
#ifdef 如果宏已经定义,则编译下面代码
#ifndef 如果宏没有定义,则编译下面代码
#elif 如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#elif预处理指令等效于#else和#if指令的综合
#endif 结束一个#if……#else条件编译块
#error 停止编译并显示错误信息
情形1:
#ifdef XXXX
...程序段1...
#else
...程序段2...
#endif
这表明如果标识符XXXX已被#define命令定义过,则对程序段1进行编译;否则对程序段2进行编译。
情形2:
#ifndef XXXX
...程序段1...
#else
...程序段2...
#endif
这里使用了#ifndef,表示的是if not def。
和#ifdef相反的状况。(如果没有定义标识符XXXX,那么执行程序段1,否则执行程序段2)。
情形3:
#if 常量
...程序段1...
#else
...程序段2...
#endif
这里表示,如果常量为真(非0数字),就执行程序段1,否则执行程序段2。
有两个文件,一个是debug.h,另一个是用于测试的main.c
//debug.h
#ifndef DEBUG_H
#define DEBUG_H
#define DEBUG
#ifdef DEBUG
#define debug(fmt,...)\
{\
printf("file:%s func:%s line:%d ",__FILE__,__func__,__LINE__);\
printf("----define---");\
printf(fmt,##__VA_ARGS__);\
}
//第一种 else1
#else
#define debug(fmt,...)\
{\
printf("file:%s func:%s line:%d ",__FILE__,__func__,__LINE__);\
printf("----else---");\
printf(fmt,##__VA_ARGS__);\
}
//第二种 else2 什么都不做
/*#else
#define debug(fmt,...) if(0)
*/
#endif//DEBUG
//任何时候都打印
#define error(fmt,...)\
{\
printf("file:%s func:%s line:%d ",__FILE__,__func__,__LINE__);\
printf(fmt,##__VA_ARGS__);\
}
#endif//DEBUG_H
//main.c
#include
#include"debug.h"
int main()
{
debug("1/...\n");
debug("2/。。。。\n");
//...
printf("-----------\n");
error("...error...\n");
}
输出结果:
file:main.c func:main line:8 ----define---1/...
file:main.c func:main line:11 ----define---2/。。。。
-----------
file:main.c func:main line:15 ...error...
来解释一波:
当 #define DEBUG 语句生效时,执行 #ifdef 部分语句
当 #define DEBUG 语句被注释,不生效时,执行 #else 部分语句
放在 #ifdef ... #else ... #endif 结构之外的,就是任何时候都能执行的
debug(fmt, ...)就等效于printf("fmt \n",##__VA_ARGS__);
debug("%s", “abc”);<==>printf("%s \n",“abc”);
fmt表示格式符,...为参数列表
好处是,无论输出多少个参数值,都可以以上面这种统一的形式进行输出实现!
debug("1/...\n");
debug("%s %d\n","test",10);
file:main.c func:main line:8 ----define---1/...
file:main.c func:main line:9 ----define---test 10
[#、##、__VA_ARGS__和##__VA_ARGS__的作用]