C 预处理器:编译前的文本魔法
一、引言
在 C 语言编程里,C 预处理器虽非编译器的一部分,但却是编译流程中独立且关键的环节。它本质上是个文本替换工具,会在实际编译前完成预处理工作,我们常将其简称为 CPP。
二、预处理器指令
所有预处理器命令都以井号(#)开头,且最好从第一列开始以增强可读性。下面是重要指令介绍:
指令 | 描述 |
---|---|
#define | 定义宏 |
#include | 包含源代码文件 |
#undef | 取消已定义的宏 |
#ifdef | 若宏已定义,返回真 |
#ifndef | 若宏未定义,返回真 |
#if | 给定条件为真,编译下面代码 |
#else | #if 的替代方案 |
#elif | 前面 #if 条件为假,当前条件为真,编译下面代码 |
#endif | 结束 #if...#else 条件编译块 |
#error | 遇到标准错误,输出错误消息 |
#pragma | 向编译器发布特殊命令 |
示例
#define MAX_ARRAY_LENGTH 20
#include <stdio.h>
#include "myheader.h"
#undef FILE_SIZE
#define FILE_SIZE 42
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
#ifdef DEBUG
/* Your debugging statements here */
#endif
三、预定义宏
ANSI C 定义了不少宏,可在编程中使用,但不能修改。
宏 | 描述 |
---|---|
__DATE__ | 当前日期,格式 "MMM DD YYYY" |
__TIME__ | 当前时间,格式 "HH:MM:SS" |
__FILE__ | 当前文件名,字符串常量 |
__LINE__ | 当前行号,十进制常量 |
__STDC__ | 编译器以 ANSI 标准编译时,定义为 1 |
示例
#include <stdio.h>
main()
{
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}
四、预处理器运算符
1. 宏延续运算符(\)
若宏过长,可用它分行书写。
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
2. 字符串常量化运算符(#)
把宏参数转为字符串常量。
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}
3. 标记粘贴运算符(##)
合并两个参数。
#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
4. defined()
运算符
用于常量表达式,判断标识符是否用 #define
定义过。
#include <stdio.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void)
{
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
五、参数化的宏
可模拟函数,如计算平方:
#define square(x) ((x) * (x))
#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
C 预处理器功能强大,掌握它能让 C 语言编程更加高效和灵活。