预处理指令:#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; }