关于宏和预处理器的有趣的事实
在一个c程序中,程序中所有的#都是由预处理器处理的,这是由编译器调用的特殊程序,在一个程序术语中,预处理器需要一个c程序,同时会产生一个没有#的c程序。
以下是有关C中预处理器的一些有趣的事实
(1)
当我们使用
include
指令时,将包含的头文件(预处理后)的内容复制到当前文件。
角括号 < 和 > 指示预处理程序查看保存所有头文件的标准文件夹。双引号 “ 和 ” 指示预处理器查看当前文件夹,用“ ”往往是我们自己写的头文件,基本都是和我们当前程序处于同一文件目录下,的如果文件不存在于当前文件夹中,则在所有头文件的标准文件夹中。
角括号 < 和 > 指示预处理程序查看保存所有头文件的标准文件夹。双引号 “ 和 ” 指示预处理器查看当前文件夹,用“ ”往往是我们自己写的头文件,基本都是和我们当前程序处于同一文件目录下,的如果文件不存在于当前文件夹中,则在所有头文件的标准文件夹中。
(2)当我们对常量使用define时,预处理器产生一个C程序,其中定义的常量被搜索,匹配的令牌被替换为给定的表达式。
//#include<stdio.h> #define max 100 int main() { printf("max is %d", max); return 0; } // Output: max is 100 // Note that the max inside "" is not replaced
3)宏可以使用参数的函数,不会检查参数的数据类型。例如,以下宏INCREMENT(x)可用于任何数据类型的x。
#include <stdio.h> #define INCREMENT(x) x+2 int main() { char *ptr = "HELLO"; int x = 10; printf("%s ", INCREMENT(ptr));//字符串后移两位 printf("%d", INCREMENT(x));//x+2 return 0; } // Output: LLO 12
4)在宏扩展之前,宏参数不被评估。例如考虑以下程序
#include<stdio.h> #define HAHA(a, b) a * b int main() { int m = HAHA(2+3, 3+5); printf("%d", m); return 0; } 结果:16
5)传递给宏的令牌可以使用operator ##称为令牌粘贴运算符进行连接。
#include<stdio.h> #define MERGE(a, b) a##b //将a 和 b 拼接 int main() { printf("%d\n", MERGE(12, 13)); return 0; }
OUTPUT:1213
6)传递给宏的令牌可以使用#转换为sting文字
#include <stdio.h> #define get(a) #a int main() { // HELLO is changed to "HELLO" printf("%s", get(HELLO)); } // Output: HELLO
7)宏可以使用'\'写入多行。最后一行不需要“\”。
#include<stdio.h> #define Manyline(i, limit) while(i < limit) \ { \ printf("hello!"); \ i++; \ } int main() { int i = 0; Manyline(i,3); return 0; }
8)有争议的宏应该避免,因为它们有时会引起问题。并且内联函数应该是首选的,因为内联函数中有类型检查参数评估。从C99起,C语言也支持内联函数。
例如考虑以下程序。从第一眼看,输出似乎是1,但它产生36作为输出。
#include<stdio.h> #define CHENGFA(a, b) a*b int main() { printf("%d", 36/CHENGFA(6,6)); return 0; }//没有用内联函数
输出为36 运算时36/6*6
如果我们使用内联函数,我们得到预期的输出。此外,上述第四点给出的程序可以使用内联函数进行更正。
9)预处理器还支持通常用于条件编译的if-else指令。
#include<stdio.h> int main() { #if 3 >= 2 printf("Trace Message"); #endif }
10)头文件可能直接或间接包含多于一次,这导致重新声明相同变量/功能的问题。为了避免这个问题,像指令定义,IFDEF和IFNDEF使用。
11)有一些标准的宏可用于打印程序文件(__FILE__),编译日期(__DATE__),编译时间(__TIME__)和行代码(__LINE__)
#include <stdio.h> int main() { printf("Current File :%s\n", __FILE__ ); printf("Current Date :%s\n", __DATE__ ); printf("Current Time :%s\n", __TIME__ ); printf("Line Number :%d\n", __LINE__ ); return 0; }
output:
/*Current File :de1.c
Current Date :May 17 2017
Current Time :21:32:54
Line Number :8*/