C语言-预处理

本文最后更新于:1 年前

编译器会将预处理的结果保存到和源文件同名的 .i 文件中

#include 文件包含命令

  • 使用尖括号< >,编译器会到系统路径下查找头文件;

  • 使用双引号” “,编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找

#define 宏定义

  • 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用 #undef 命令

  • 代码中的宏名如果被引号包围,那么预处理程序不对其作宏代替(所以printf中打印的宏定义字符不会被替换)

  • 带参数的宏定义需要格外小心,最好每一部分都用括号包住 #define SQ(y) ((y)*(y))

  • #用来将宏定义中的参数转换为字符,也就是在宏参数的开头和末尾添加引号。如果x是一个宏参量,那么#x可以把参数名转化成相应的字符串。该过程称为字符串化(stringizing)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #incldue <stdio.h>
    #define PSQR(x) printf("the square of" #x "is %d./n",(x)*(x))
    int main(void)
    {
    int y =4;
    PSQR(y);
    PSQR(2+4);
    return 0;
    }

    输出结果:

    the square of y is 16.

    the square of 2+4 is 36.

    第一次调用宏时使用“y”代替#x;第二次调用时用“2+4”代#x。

  • ##称为连接符,用来将宏参数或其他的串连接起来,把两个语言符号组合成单个语言符号

    #define CON1(a, b) a##e##b

    printf(“%f\n”, CON1(8.5, 2));

    会被展开为

    printf(“%f\n”, 8.5e2);

预定义宏

ANSI C 规定了以下几个预定义宏,它们在各个编译器下都可以使用:

  • __LINE__:表示当前源代码的行号;
  • __FILE__:表示当前源文件的名称;
  • __DATE__:表示当前的编译日期;
  • __TIME__:表示当前的编译时间;
  • __STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;
  • __cplusplus:当编写C++程序时该标识符被定义

条件编译

  • #if 后面跟的是“整型常量表达式”,而 #ifdef 和 #ifndef 后面跟的只能是一个宏名

  • #ifdef 可以认为是 #if defined 的缩写

  • VS/VC 下,当以 Debug 模式编译程序时,宏 _DEBUG 会被定义,可用于条件编译区分release版

#error 阻止编译

  • 在编译期间产生错误信息,并阻止程序继续编译
1
2
3
#ifndef __cplusplus
#error 当前程序必须以C++方式编译
#endif