c预处理器
c语言通过预处理器提供了一些语言功能。预处理器是编译单独执行的一个步骤。所有的预处理器命令都是以#开头。例如文件包含指令#include,还有宏定义#define指令。
文件包含
文件包含指令#include,用于在编译期间把指定文件的内容包含进当前文件中。格式如
#include或#include"文件名"
两者的不同在于后者用引号引起来的文件会在源文件所在的位置查找该文件,相当于自己定义头文件。而前者会到文件存放指定的系统库环境位置查找。在vc++6.0中是自定义安装位置下的:\Microsoft Visual Studio\VC98\Include路径。如果在源文件中没有查找到用引号引起来的文件,那么才会去系统库环境中查找。
宏替换
宏定义形式:
#define 名字 替换文本
后续所有出现名字记号的地方都将被替换成替换文本,替换文本可以是任意字符串,如果替换文本过长,可以用反斜杠符号\连接该行与下一行。替换只对记号进行,在对引号内的记号不会产生替换。例如NAME是一个宏定义名,在printf(“NAME”)中的NAME不会被替换。
c预处理器宏参数,字符串常量化运算符,标记粘贴运算##
参数化的宏模拟函数,与函数不同的是宏参数之间仍然是替换,并非值的传递。
在替换文本中,参数名以#作为前缀则结果将被扩展为由实际参数替换该参数的带引号的字符串。例如
#include<stdio.h>
#define name(x) printf(#x"=%d\n",x);
void main()
{
name(5)
}
运行结果
也就是说形如 printf(“5"”=%d\n",x);
预处理器运算符##为宏扩展提供了一种连接实际参数的手段,如
#include<stdio.h>
#define name(x,y) printf(#x ## #y"\n");
void main()
{
name(5,8)
}
运行结果
也就是形如把#x#y相连接起来了。
重要的预处理器指令
指令 | 作用解释 |
---|---|
#define | 定义宏 |
#include | 包含一个源代码文件 |
#undef | 取消已定义的宏 |
#ifdef | 如果宏已经定义,则返回真 |
#ifndef | 如果宏没有定义,则返回真 |
#if | 如果给定条件为真,则编译下面代码 |
#else | #if 的替代方案 |
#elif | 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码 |
#endif | 结束一个 #if……#else 条件编译块 |
#error | 当遇到标准错误时,输出错误消息 |
#pragma | 使用标准化方法,向编译器发布特殊的命令到编译器中 |
指令实例
#include<stdio.h>
#ifndef PI //判断PI有没有被定义,如果没有执行下面语句直到#endif结束
#define PI 3.1415926 //定义PI为3.1415926
#undef PI //取消PI定义
#define PI 3.14 //重新定义为3.14
#endif //结束
#ifdef PI //如果PI被定义,则执行下面宏替换
#define R 2
#endif
#if !defined(PI) //表达式define(名字),如果名字被定义返回值为1,编译下面宏替换,反之为0,在这里因为加了!,所以相反
#define R 4
#else //如果已经被定义,编译下面宏替换
#define NAME printf("R=%d\n",R);
#endif
void main()
{
NAME
printf("PI=%f\tS=%f\n",PI,PI*R*R);
}
运行结果
ANSI C中定义的宏
ANSI C中定义了许多宏。如下
宏 | 作用解释 |
---|---|
DATE | 当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。 |
TIME | 当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。 |
FILE | 当前文件名,一个字符串常量。 |
LINE | 当前行号,一个十进制常量。 |
实例
#include<stdio.h>
void main()
{
printf("date:%s\n",__DATE__);
printf("file:%s\n",__FILE__);
printf("time:%s\n",__TIME__);
printf("line:%d\n",__LINE__);
}
运行结果
以上部分参考
菜鸟教程