C预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。
所有的预处理器命令都是以井号(#)开头。它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始。
(1) 预处理器实例
1 // 包含一个源代码文件(从系统库中获取 stdio.h,并添加文本到当前的源文件中) 2 #include <stdio.h> 3 4 // 定义宏(把代码中所有的FILE_SIZE替换为20) 5 #define FILE_SIZE 20 6 // 取消已定义的宏 7 #undef FILE_SIZE 8 9 // 如果定义了宏MESSAGE,则执行处理语句 10 #ifdef MESSAGE 11 /* Do something */ 12 #endif 13 // 如果有定义宏没MESSAGE,则执行处理语句 14 #ifndef MESSAGE 15 /* Do something */ 16 #endif 17 18 // 如果给定条件为真,则编译下面代码 19 #if Something TRUE 20 /* Do something */ 21 // 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码 22 #elif Something TRUE 23 /* Do something */ 24 // #if 的替代方案 25 #else 26 /* Do something */ 27 // 结束一个 #if...#else 条件编译块 28 #endif
(2) 预定义宏
1 #include <stdio.h> 2 3 // 预定义宏 4 int main() { 5 printf("File :%s ", __FILE__); // 当前文件名,一个字符串常量 / output:TestD.c 6 printf("Date :%s ", __DATE__); // 当前日期,一个以"MMM DD YYYY"格式表示的字符常量 / output:Nov 10 2017 7 printf("Time :%s ", __TIME__); // 当前时间,一个以"HH:MM:SS"格式表示的字符常量 / output: 13:50:21 8 printf("Line :%d ", __LINE__); // 这会包含当前行号,一个十进制常量 / output:8 9 printf("ANSI :%d ", __STDC__); // 当编译器以 ANSI 标准编译时,则定义为 1 / output:1 10 return 0; 11 }
(3) 预处理器运算符&参数化的宏
1 #include <stdio.h> 2 3 // 预处理器运算符&参数化的宏 4 // 宏延续运算符[] & 字符串常量化运算符[#] 5 #define message_between(min, max) 6 printf("Size must between" #min " and " #max "! ") 7 8 // 标记粘贴运算符[##] 9 #define tokenpaster(n) printf("token" #n " = %d", token##n) 10 11 // defined()运算符 12 #if !defined (MESSAGE_NOTNULL) 13 #define MESSAGE_NOTNULL "Message not be null! " 14 #endif 15 16 // 参数化的宏(省略括号会导致运算错误) 17 #define MAX(x,y) ((x)>(y)?(x):(y)) 18 #define SWAP(x,y) {x=x+y;y=x-y;x=x-y;} 19 20 int main() { 21 message_between(8, 20); 22 int token1 = 40; 23 // 相当于: printf("token1 = %d", token1); 24 tokenpaster(1);// token1 = 40 25 printf(MESSAGE_NOTNULL); //Message not be null! 26 printf("Max number is: %d ", MAX(10, 17)); // Max number is: 17 27 int x = 20, y = 27; 28 SWAP(x, y); 29 printf("After change: x=%d, y=%d ", x, y); // After change: x=27, y=20 30 return 0; 31 }