预处理
-
所谓预处理是指进行编译的第一遍扫描(词法扫描和语法分析)之前所做的工作。系统会自动将’#'开头的预处理部分做进行处理,处理完毕后进行进入源程序的编译阶段。
-
C语言中提供多种预处理功能,如宏定义、文件包含、条件编译等。
-
预定义
-
在C语言源程序中允许用一个标识符表示符号,称为宏,被定义为宏的标识符称为宏名。对程序中出现的所有宏名,都用宏定义中的符号串去替换,这称为宏替换或者宏展开。
-
预定义符号表:
符号 实例 含义 _FILE_ 正在预编译源文件名 _LINE_ 文件在当前的行号 _FUNCTION_ 当前所在的函数名 _DATE_ 预编译文件的日期 _TIME_ 预编译文件的时间 _STDC_ 如果编译器遵循ANSIC,则值为1
-
-
宏定义
- 宏替换是在预处理时自动完成的
1.无参宏定义
#define 标识符 字符串
- 宏定义用宏名来表示一串字符串符号,在宏展开的时候又以该符号去掉宏名,这只是一种简单的替换预处理程序不对它做任何的检查
- 宏定义不是声明或语句,在行末不必加分号,如加上分号会连分号一起替换
- 宏定义的作用域从从宏定义命名起到源程序结束,如要终止其作用域可使用#undef命令来取消宏作用域。
- 宏名在源程序中若用引号括起来则预处理程序则不对齐进行宏替换。
- 习惯上宏名一般用大写字母。
- 可对输出格式做宏定义,减少麻烦。
2.带参宏定义
-
C语言张允许宏带有参数,在宏定义中的参数被称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏子在调用时不仅要宏展开,而且还要用实参去替换形参。一般形式如下:
#define 宏名(形参表) 字符串
-
带惨宏定义中,宏名和参数表之间不能有空格出现。
#define MAX (a,b) (a>b)?a:b
这将会被认为是无参宏定义,宏名MAX代表字符串"(a,b) (a>b)?a:b"。
-
在带参宏定义中,形式参数不分配内存单元,因此不必做类型定义。这与函数中的情况是不同的,在函数中,形参和实参是两个不同的量,各自有各自的作用域,调用时要把实参值赋给形参,进行值传递。而在带参数宏定义中只是符号替换不存在值传递的问题。
-
在宏定义中,形参是标识符,而宏调用中的实参可以使表达式。这与函数调用是不同的,函数调用时要把实参表达式的值求出来再赋予形参,而宏替换中对实参表达式不做计算直接原样替换。(为避免引起问题,应该在采纳数两侧加括号,还应在整个符号串外加括号)。
-
文件包含
-
文件包含语句的功能是吧指定的文件插入该语句行位置,从而把指定的文件和当前源程序文件连成一个源文件。
-
包含形式如下:
#include "文件名" #include <文件名>
-
这两种包含形式的不同点:
1.使用<>表示的在系统头文件目录去查找(头问价目录可以由用户来指定)。
2.使用双引号则表示首先在当前源文件的目录查找,若未找到才到系统头文件目录去查找。
-
-
一个include命令只能包含一个指定的文件。
-
文件包含允许嵌套
-
-
条件编译
-
使编译器按照不同的条件去编译不同的代码,主要由一下三种形式:
#ifdef 标识符 程序段1 #else 程序段2 #endif
它表示如果标识符已经被#define语句定义过,则编译程序段1,否则编译程序段2,。如果没有程序段2,则本格式中的#else可以没有。
#ifndef 标识符 程序段1 #else 程序段2 #endif
与第一种形式的功能正好相反。
#if 常量表达式 程序段1 #else 程序段2 #endif
它的功能是,如果常量表达式的值为真(非0),则编译程序段1,否则便于程序段2.因此可以是程序在不同的条件下完成不同的功能。
-