C语言 预处理器



  • 预处理器

    C预处理器不是编译器的一部分,而是编译过程中的一个单独步骤。简单地说,C预处理器只是一个文本替换工具,它指示编译器在实际编译之前进行所需的预处理。我们将把C预处理器称为CPP。所有预处理器命令都以一个哈希符号(#)开头。它必须是第一个非空字符,为了可读性,预处理指令应该从第一列开始。下面列出了所有重要的预处理器指令
    指令 说明
    #define 替代预处理器宏。
    #include 从另一个文件插入特定的标头。
    #undef 未定义预处理器宏。
    #ifdef 如果定义了此宏,则返回true。
    #ifndef 如果未定义此宏,则返回true。
    #if 测试编译时间条件是否为真。
    #else #if的替代方法。
    #elif #else和#if在一条语句中。
    #endif 有条件地结束预处理程序。
    #error 在stderr上显示错误消息。
    #pragma 使用标准化方法向编译器发出特殊命令。
  • 预处理器示例

    分析以下示例以了解各种指令。
    
    #include <stdio.h>
    
    int main() {
    
       printf("File :%s\n", __FILE__ );
       printf("Date :%s\n", __DATE__ );
       printf("Time :%s\n", __TIME__ );
       printf("Line :%d\n", __LINE__ );
       printf("ANSI :%d\n", __STDC__ );
    
    }
    
    
  • 预处理器示例

    C预处理器提供以下运算符以帮助创建宏-
    宏延续(\)运算符
    宏通常限于一行。宏延续运算符(\)用于延续对于单行来说太长的宏。例如-
    
    #define  message_for(a, b)  \
       printf(#a " and " #b ": We love you!\n")
    
    
    字符串化(#)运算符
    字符串化或数字符号运算符('#')在宏定义中使用时,会将宏参数转换为字符串常量。该运算符只能在具有指定参数或参数列表的宏中使用。例如-
    
    #include <stdio.h>
    
    #define  message_for(a, b)  \
       printf(#a " and " #b ": We love you!\n")
    
    int main(void) {
       message_for(Carole, Debra);
       return 0;
    }
    
    
    令牌粘贴(##)运算符
    宏定义中的令牌粘贴运算符(##)组合了两个参数。它允许将宏定义中的两个单独的标记合并为一个标记。例如-
    
    #include <stdio.h>
    
    #define tokenpaster(n) printf ("token" #n " = %d", token##n)
    
    int main(void) {
       int token34 = 40;
       tokenpaster(34);
       return 0;
    }
    
    
    上面编译运行后输出:token34 = 40
    发生这种情况是因为此示例导致了预处理器的以下实际输出-
    
    printf ("token34 = %d", token34);
    
    
    此示例显示了将token ## n连接到token34的情况,这里我们同时使用了字符串化和令牌粘贴 。
    defined()运算符
    在常量表达式中使用预处理器定义的运算符,以确定是否使用#define定义了标识符。如果定义了指定的标识符,则该值为true(非零)。如果未定义符号,则该值为false(零)。定义的运算符指定如下-
    
    #include <stdio.h>
    
    #if !defined (MESSAGE)
       #define MESSAGE "You wish!"
    #endif
    
    int main(void) {
       printf("Here is the message: %s\n", MESSAGE);  
       return 0;
    }
    
    
  • 参数化的宏

    CPP的强大功能之一是能够使用参数化宏模拟函数。例如,我们可能有一些代码可以对数字平方,如下所示:
    
    int square(int x) {
       return x * x;
    }
    
    
    我们可以使用宏如下重写代码:
    
    #define square(x) ((x) * (x))
    
    
    具有参数的宏必须先使用#define指令定义,然后才能使用。参数列表用括号括起来,并且必须紧随宏名称之后。宏名称和右括号之间不允许有空格。例如-
    
    #include <stdio.h>
    
    #define MAX(x,y) ((x) > (y) ? (x) : (y))
    
    int main(void) {
       printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
       return 0;
    }