预编译
在前面各章中,已多次使用过以#号开头的预处理命令
如包含命令 #include <stdio.h>,宏定义命令#define Pl 3.1415
在源程序中这些命令都放在函数之外,而且一般都放在源文件的前面它们称为预处理部分
无参宏定义
一般形式:#define 标识符 字符串
字符串可以是常数,表达式,格式串等
宏定义不是说明或语句,在行未不必加分号,如加上分号则连分号也-起置换
宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用 #undef 命令
宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。
宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。宏展开时由预处理程序层层代换。
习惯上宏名用大写字母表示,以便于与变量区别,但也允许用小写字
可用宏定义表示数据类型,使书写方便
例如: #define INTEGER int
在 #include <windows.h>
关于typedef后面一篇文章会详细讲解,暂时先了解typedef和define的区别
区别:宏定义只是简单的字符串替换,是在预处理完成的,而 typedef是在编译时处理的,而typedef是在编译时处理的,它不是作简单的代换,而是对类型说明符重新命名。被命名的标识符具有类型定义说明的功能。
如:
(正规语句)
Typedef WNDCLASSAWNDCLASS
注意typedef 语句最后有分号
带参宏定义
C语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。
对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参
带参宏定义的一般形式为:
字符串#define 宏名(形参表)
带参宏定义中,宏名和形参表之间不能有空格出现。
例如把:
#define MAX(a,b)(a>b)?a:b
写为:
(a.b)?a:b#define MAX (a.b)
对于带参的宏定义有以下问题需要说明
在带参宏中,形式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值。要用它们去代换形参,因此必须作类型说明。
这是与函数中的情况不同的,在函数中,形参和实参是两个不同的量各有自己的作用域,调用时要把实参值赋予形参,进行“值传递”而在带参宏中,只是符号代换,不存在值传递的问题。
在宏定义中,字符串内的形参通常要用括号括起来以避免出错。一上例中的宏定义中(y)*(y)表达式的y 都用括号括起来,因此结果是正确的。如果去掉括号,把程序改为以下形式:
带参的宏和带参函数很相似,但又本质上的不同,除上面已谈到的各点外,把同一表达式用函数处理与用宏处理两者的结果有可能是不同的。
宏定义也可用来定义多个语句,在宏调用时,把这些语句又代换到源程序内。
关于文件包含
文件包含中的文件名可以用双引号括起来,也可以用尖括号括起来例如以下写法都是允许的:
#include <stdio.h>
#include “stdio.h'
但是这两种形式是有区别的:使用尖括号表示在包含文件目录中区查找(包含目录是由用户在设置环境时设置的),而不是在源文件目录区查找。
使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中区查找。用户编程时可根据自己文件所在的目录来选择某-种命令形式。
关于条件编译
第一种,它的功能是,如果标识符已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
标识符#ifdef
程序段1
#else
程序段2#enfif
如果没有程序段2(它为空),本格式符中的#else可以没有,既可以写为:
#ifdef 标识符
程序段
#endif
第二种,
标识符#ifndef程序段1
#else
程序段2
#endif
第三种
If 常量表达式程序段
#else
程序段
#endif