一、明示常量: #define
#define预处理器指令和其他预处理器一样,以#号作为一行的开始。ANSI和后来的标准都允许#前面有空格或者制表符,二千还允许在# 和指令的其余部分有空格。旧版本的C 要求指令从一行最左边开始,而且#指令其余部分之间不能有空格。
指令可以出现在源文件的任何地方,其定义从指令出现的地方到改文件结尾有效。可以使用#define来定义明示常量(也叫符号常量)
#include <stdio.h>
#define TWO 2 /* TWO 2 */
#define OW "I am \
chengxuy"
#define FOUR TWO*TWO
#define PX printf("X is %d\n", x)
#define FMT "x is %d.\n"
int main()
{
int x = TWO;
PX;
x = FOUR;
printf(FMT, x);
printf("%s\n", OW);
return 0;
}
每行#define(逻辑行)都有三部分组成。第一部分是#define 本身;第二部分是选定的缩写,也称为宏,有些宏代表值,这些宏被称为类对象宏,必须遵守C变量的命名规则;第三部分(指令行的其余部分)称为替换列表或替换体。一旦预处理器在程序找到宏的示实例后,就会用替换体代替该宏(有例外)。从宏变成最终替换文本的过程被称为宏展开。
1、重定义常量
假设先把LIMIT定义为20,稍后在改文件中又把它定义为25,这个过程称为重定义常量。
二、、在#define中使用参数
在#define中使用参数可以创建外形和作用域函数类似的类函数宏。带参数的宏看上去很像函数。类函数宏定义的圆括号中可以可以有一个或多个参数,随后这些参数出现在替换体中。
#include <stdio.h>
#define SQUARE(X) X*X
#define PR(X) printf("The result is %d.\n", X)
int main()
{
int x = 5;
int z = 0;
printf("x=[%d], z=[%d]\n", x, z);
z = SQUARE(x);
printf("x=[%d], z=[%d]\n", x, z);
PR(z);
PR(x);
return 0;
}
1、用宏参数创建字符串:#运算符
如果x是一个宏形参,那么#x就是转换为字符串“X”形参名,这个过程称为字符串化。
#include <stdio.h>
#define PSQR(x) printf("the square of " #x " is %d.\n", ((x)*(x)))
int main()
{
int y = 5;
PSQR(y);
PSQR(2 + 4);
return 0;
}
2、预处理器黏合剂: ##运算符
与#运算符类型, ##运算符可用于类函数宏的替换部分。而且,##还可用于对象宏的替换部分。##运算符把俩个记号组成一个记号。例如:
#define XNAME(n) x ## n
#include <stdio.h>
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x " #n " = %d\n", x ## n);
int main()
{
int XNAME(1) = 14;;
int XNAME(2) = 20;;
int x3 = 20;
PRINT_XN(1);
PRINT_XN(2);
PRINT_XN(3);
return 0;
}
3、变参宏: … 和 _ _VA_ARGS_ _
一些函数接受数量可变的参数。stdvar.h提供了工具,让用户定义带可变参数的函数。
通过把宏参数列表最后的参数写成省略号(即三个点 …)来实现这一功能。预定义宏_ _VA_ARGS_ _
可用在替换部分中,表示省略号代表什么。
#define pr(…) printf(_ _VA_ARGS_ _
)
#include <stdio.h>
#include <math.h>
#define PR(X, ...) printf("Message " #X " : " __VA_ARGS__)
int main()
{
double x = 48.0;
double y = 9.0;
PR(1, "x = %g\n", x);
PR(2, "X = %.2f, y= %.4f\n", x, y);
return 0;
}
三、文件包含:#include
四、其他指令
1、#undef指令
#undef指令用于取消已定义的#define指令。例如
#define LIMIT 400
#undef LIMIT // 移除上面的定义
即使原来没有定义LIMIT,取消LIMIT的定义仍然有效
2、条件编译
可以使用其他指令创建条件编译。可以使用这些指令告诉编译器根据编译时的条件执行或忽略信息(或代码块)、。
1、#ifdef、#else和#endif指令
#ifdef MAVIS
#include "horse.h" // 如果已经用#define定义了MAVIS,则执行下面的命令
#define STABLES 5
#else
#include "cow.h" // 如果没有用#define定义了MAVIS,则执行下面的命令
#define STABLES 5
#endif
2、#ifndef指令
#ifndef指令与ifdef指令的用法类似,也可以和#else、#endif一起使用。
#ifndef指令判断后面的标识符是否是未定义的。
3、预定义宏
宏 | 含义 |
---|---|
_ _DATE_ _ | 预处理的日期("Mmm dd yyyy"形式的字符串字面量 ,如Nov 23 2013) |
_ _FILE_ _ | 表示当前源代码文件名的字符串字面量 |
_ _LINE_ _ | 表示当前源代码文件中行号的整形常量 |
_ _STDC_ _ | 设置为1是,表明遵循C标准 |
_ _STDC_HOSTED_ _ | 本机环境设置为1,否则设置为0 |
_ _STDC_VERSION_ _ | 支持C99标准,设置为199901L;支持C11标准,设置为201112L |
_ _TIME_ _ | 翻译代码时间,格式为“hh:mm :ss” |
_ _func_ _ | 代表函数名的字符串(是预定义标识符) |
4、#pragma
#pragma把编译器指令放入源代码中。例如在开发C99时,标准被称为C9X,可以使用下面的编译指示让编译器支持C9X:
#pragma c9x on
5、内联函数
inline static void asd()
{
}