在C程序中,所有以开头的行都由预处理程序处理,预处理程序是编译器调用的特殊程序。在一个非常基本的术语中,预处理器采用C程序并生成另一个没有#的 C程序。

以下是关于C中预处理器的一些有趣的事实
.1)当我们使用include 指令时,包含的头文件(在预处理之后)的内容被复制到当前文件。
Angular括号<>指示预处理器查看保存所有头文件的标准文件夹。双引号指示预处理器查看当前文件夹,如果该文件不在当前文件夹中,则在所有头文件的标准文件夹中。
2)当我们使用define时对于常量,预处理器生成一个C程序,其中搜索定义的常量,匹配的标记用给定的表达式替换。例如,在以下程序中,max定义为100。

#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
int main()
{
    char *ptr = "GeeksQuiz";
    int x = 10;
    printf("%s  ", INCREMENT(ptr));
    printf("%d", INCREMENT(x));
    return 0;
}
// Output: eeksQuiz 11

4)在宏扩展之前不评估宏参数。例如,考虑以下程序

#include <stdio.h>
#define MULTIPLY(a, b) a*b
int main()
{
    // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
    printf("%d", MULTIPLY(2+3, 3+5));
    return 0;
}
// Output: 16

5)传递给宏的标记可以使用运算符##连接,称为Token-Pasting运算符。

#include <stdio.h>
#define merge(a, b) a##b
int main()
{
    printf("%d ", merge(12, 34));
}
// Output: 1234

6)传递给宏的标记可以通过在它之前使用#转换为字符串文字。

#include <stdio.h>
#define get(a) #a
int main()
{
    // GeeksQuiz is changed to "GeeksQuiz"
    printf("%s", get(GeeksQuiz));
}
// Output: GeeksQuiz

7)宏可以使用'\'以多行写入。最后一行不需要'\'。

#include <stdio.h>
#define PRINT(i, limit) while (i < limit) \
                        { \
                            printf("GeeksQuiz "); \
                            i++; \
                        }
int main()
{
    int i = 0;
    PRINT(i, 3);
    return 0;
}
// Output: GeeksQuiz  GeeksQuiz  GeeksQuiz

8)应该避免带参数的宏,因为它们有时会引起问题。并且内联函数应该是首选,因为内联函数中有类型检查参数评估。从C99开始,C语言也支持内联函数。
例如,考虑以下程序。从第一眼看,输出似乎是1,但它产生36作为输出。

#define square(x) x*x
int main()
{
  int x = 36/square(6); // Expended as 36/6*6
  printf("%d", x);
  return 0;
}
// Output: 36

如果我们使用内联函数,我们得到预期的输出。此外,上述第4点中给出的程序可以使用内联函数进行纠正。

inline int square(int x) { return x*x; }
int main()
{
  int x = 36/square(6);
  printf("%d", x);
  return 0;
}
// Output: 1

9)预处理器还支持if-else指令,这些指令通常用于条件编译。

int main()
{
#if VERBOSE >= 2
  printf("Trace Message");
#endif
}

10)头文件可以直接或间接地包括多于一次,这导致相同变量/功能的重新声明的问题。为了避免这个问题,像指令定义IFDEFIFNDEF使用。
11)有一些标准宏可用于打印程序文件(__FILE__),编译日期(__DATE__),编译时间(__TIME__)和C代码行号(__LINE__)

#include <stdio.h>
intmain()
{
   printf("Current File :%s\n", __FILE__ );
   printf("Current Date :%s\n", __DATE__ );
   printf("Current Time :%s\n", __TIME__ );
   printf("Line Number :%d\n", __LINE__ );
   return0;
}
/* Output:
Current File :C:\Users\GfG\Downloads\deleteBST.c
Current Date :Feb 15 2014
Current Time :07:04:25
Line Number :8 */
有关C中宏和预处理器的有趣事实-IDC帮帮忙