预处理指令:#define、#include、#ifdef、#else、#endif、#ifndef、#if、#elif、#line、#error、#pragma
预处理器不做计算,不对表达式求值。它只进行文本替换。
宏定义还可以包含其他宏(一些编译器可能不支持这种嵌套功能)。
示例
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //C99特性
#include <string.h>
#include <math.h>
#include <ctype.h>
// 可用反斜杠切换到下一行书写
#define ROW "this is tow row, \
i love you!"
// 定义函数宏
// SQUARE是宏标识符,X是宏参数,X*X是替换列表,程序中出现SQUARE(X)的地方都会被X*X替换。
#define SQUARE(X) X*X
// 注意: 避免在宏中出现递增或递减运算符++、--
// 例如,++x*++x,在C标准中并未规定这种情况的计算顺序,不同的编译器可能产生不同的计算结果。
#define PR(X) printf("The result is %d.\n", X)
// #x会被替换成宏参数
#define PSQR(x) printf("The square of " #x " is %d.\n", ((x)*(x)))
// 预处理器黏合剂:##运算符,把两个记号组合成一个记号
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x" #n " = %d\n", x ## n)
int main(int argc, char* argv[])
{
int x = 5;
int z;
int XNAME(1) = 14; // 变成 int x1 = 14;
int XNAME(2) = 20; // 变成 int x2 = 20;
int x3 = 30;
PRINT_XN(1); // 变成 printf("x1 = %d\n", x1);
PRINT_XN(2); // 变成 printf("x2 = %d\n", x2);
PRINT_XN(3); // 变成 printf("x3 = %d\n", x3);
printf("x = %d\n", x);
z = SQUARE(x);
printf("Evaluating SQUARE(x):");
PR(z);
z = SQUARE(2);
printf("Evaluating SQUARE(2):");
PR(z);
printf("Evaluating SQUARE(x+2):");
//宏调用在编译之前把参数记号传递给程序
PR(SQUARE(x + 2));//因为预处理器不做计算,这里等价于PR(x+2*x+2)
printf("Evaluating 100/SQUARE(2):");
PR(100 / SQUARE(2));
printf("x is %d.\n", x);
printf("Evaluating SQUARE(++x): ");
PR(SQUARE(++x));
printf("After incrementing, x is %x.\n", x);
PSQR(2+4);
system("pause");
return 0;
}
运行测试
示例:预处理宏
//#pragma 设置编译器参数
//#pragma c9x on
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //C99特性
#include <string.h>
#include <math.h>
#include <ctype.h>
//条件编译
#ifdef MAVIS
//旧编译器代码块必须左对齐
#define STABLES 5
#else
//旧编译器代码块必须左对齐
#define STABLES 15
#endif
//#ifndef通常用来防止重复定义宏或重复包含头文件
//如果宏未定义
#ifndef SIZE
//新编译器支持代码块缩进
#define SIZE 100
#endif
//防止重复包含头文件
#ifndef HADE_H_
#define HEAD_H_
#endif
#if SYS == 1
#elif SYS == 2
#elif SYS == 3
#else
#endif
//较新编译器提供了defined()
//如果定义了IBMPC宏,defined()则返回1,否则返回0
#if defined (IBMPC)
#elif defined (VAX)
#elif defined (MAC)
#else
#endif
//空宏
#define EMPTY
#define LIMIT 400
//取消之前的#define LIMIT定义
#undef LIMIT
int main(int argc, char* argv[])
{
//内置的预定义宏
printf("__DATE__: %s\n", __DATE__); //输出时间 Mmm dd yyyy
printf("__FILE__: %s\n", __FILE__); //输出当前代码文件路径
printf("__LINE__: %d\n", __LINE__); //输出当前源代码行号
//printf("__STDC__: %d", __STDC__); //1:遵循C标准
printf("__STDC_HOSTED__: %d\n", __STDC_HOSTED__); //1:本机环境
//printf("__STDC_VERSION__: %d\n", __STDC_VERSION__);//199901L:支持C99标准,201112L:支持C11标准
printf("__TIME__: %s\n", __TIME__);//当前时间 hh:mm:ss
printf("__func__: %s\n", __func__);
//#line指令重置__LINE__和__FILE__宏报告的行号和文件名。
#line 1000 // 把当前行号重置为1000
#line 10 "cool.c" // 把行号重置为10,把文件名重置为cool.c
#if __STDC_VERSION__ != 201112l
//#error Not C11
#endif
system("pause");
return 0;
}
运行测试
示例:泛型选择(C11)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //C99特性
#include <string.h>
#include <math.h>
#include <ctype.h>
//泛型选择(C11)
//根据X的类型来匹配值
//例如,X是int类型,则返回"int"
#define MYTYPE(X) _Generic((X), \
int : "int", \
float: "float", \
double: "double", \
default: "other" \
)
int main(int argc, char* argv[])
{
int d = 5;
printf("%s\n", MYTYPE(d)); //输出"int"
printf("%s\n", MYTYPE(2.0*d)); //输出"double"
printf("%s\n", MYTYPE(3L)); //输出"other"
printf("%s\n", MYTYPE(&d)); //输出"other"
system("pause");
return 0;
}