文章目录
C 预处理器
不是编译器
的组成部分,但是它是编译过程
中一个单独的步骤
。
简言之,C 预处理器只不过是一个文本替换工具
而已,它们会指示编译器
在实际编译
之前完成所需的预处理
。我们将把 C 预处理器
(C Preprocessor
)简写为CPP
。
所有的预处理器
命令都是以井号(#
)开头。它必须是第一个非空字符
,为了增强可读性,预处理器指令
应从第一列开始
。
下面列出了所有重要的预处理器
指令:
序号 | 指令 | 描述 |
---|---|---|
1 | #define | 定义宏 |
2 | #include | 包含 一个源代码文件 |
3 | #undef | 取消 已定义的宏 |
4 | #ifdef | 如果宏已经定义 ,则返回真 |
5 | #ifndef | 如果宏没有定义 ,则返回真 |
6 | #if | 如果给定条件 为真 ,则编译 下面代码 |
7 | #else | #if 的替代方案 |
8 | #elif | 如果前面的#if 给定条件不为真 ,当前条件为真 ,则编译下面代码 |
9 | #endif | 结束一个#if...#else 条件编译块 |
10 | #error | 当遇到标准错误 时,输出错误消息 |
11 | #pragma | 使用标准化方法 ,向编译器 发布特殊的命令到编译器中 |
1、预处理器 实例
#include <stdio.h>
指令告诉CPP
从系统库
中获取stdio.h
,并添加文本到当前的源文件
中。
2、预定义宏
ANSI C
定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。
序号 | 宏 | 描述 |
---|---|---|
1 | __DATE__ | 当前日期 ,一个以 MMM DD YYYY 格式表示的字符常量 |
2 | __TIME__ | 当前时间 ,一个以 HH:MM:SS 格式表示的字符常量 |
3 | __FILE__ | 包含当前文件名 ,一个字符串常量 |
4 | __LINE__ | 包含当前行号 ,一个十进制常量 |
5 | __STDC__ | 当编译器以 ANSI 标准 编译时,则定义为1 (STDC:Standard C) |
尝试下面的实例:
#include <stdio.h>
void 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__ );
}
对应输出结果:
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
3、预处理器 运算符
C 预处理器
提供了下列的运算符
来帮助您创建宏
:
3.1 宏延续运算符
(\
)
一个宏
通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符
(\
)。例如:
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
3.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;
}
对应输出结果:
Carole and Debra: We love you!
3.3 标记粘贴运算符
(##
)
宏定义
内的标记粘贴运算符
(##
)会合并两个参数。它允许在宏定义
中两个独立的标记被合并为一个标记。例如:
#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
对应输出结果:
token34 = 40
这个实例演示了token##n
会连接到token34
中,在这里,我们使用了字符串常量化运算符
(#
)和标记粘贴运算符
(##
)。
3.4 defined() 运算符
预处理器 defined 运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义,则值为真(非零)。如果指定的标识符未定义,则值为假(零)。下面的实例演示了 defined() 运算符的用法:
#include <stdio.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void)
{
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
对应输出结果:
Here is the message: You wish!
4、参数化的宏
CPP
一个强大的功能是可以使用参数化的宏来模拟函数。例如,下面的代码是计算一个数的平方:
int square(int x) {
return x * x;
}
使用宏重写上面的代码:
#define square(x) ((x) * (x))
在使用带有参数的宏之前,必须使用 #define 指令定义。参数列表是括在圆括号内,且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。例如:
#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;
}
对应输出结果:
Max between 20 and 10 is 20