目录

C 预处理器

本文是 C 预处理器的笔记,在 C++ 中已经不再建议使用预处理器实现功能了。

常用功能

  • 提供字符串替换

  • 提供头文件(*.h)包含

  • 通用代码模板的扩展

  • 宏最好只用于命名常量,并为一些适当的结构提供简洁的记法

  • 千万别用c预处理器修改语言的基础结构

  • 空格带来的影响

#define a(y) a_expanded(y)
a(x);// 被拓展为 a_expanded(x)
// 区别于
#define a (y) a_expanded(y)
a(x); // 被拓展为 (y) a_expanded(y)(x)

预编译处理函数

  • 函数的定义放 .c 文件,函数的声明放 .h 文件

  • 如果要使用某个 .c 文件中定义的函数,只需要 #include 这个 .c 文件对应的 .h 文件

  • .h 文件的作用:被别人拷贝。编译链接的时候不需要管 .h 文件

#define MAX_ARRAY_LENGTH 20M
#undef  FILE_SIZE
#define FILE_SIZE 42

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

#define DEBUG 1
#ifdef DEBUG
#define debug(a,b) printf(#a"\n",b)
#else
#define debug(a,b) ;
#endif

/* 字符串常量化运算符(#) */
#define message_for(a, b)  printf(#a " and " #b " : We love you!\n")
message_for(Carole, Debra); // Carole and Debra: We love you!

/* 标记粘贴运算符(##) */
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
tokenpaster(34); // printf ("token34 = %d", token34);

/* 模拟函数 */
#define square(x) ((x) * (x))
#define MAX(x,y) ((x) > (y) ? (x) : (y))

常用指令

  • #define 定义宏

  • #include 包含一个源代码文件

  • #undef 取消已定义的宏

  • #ifdef 如果宏已经定义,则返回真

  • #ifndef 如果宏没有定义,则返回真

  • #if 如果给定条件为真,则编译下面代码

  • #else

  • #elif 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码

  • #endif 结束一个 #if #else 条件编译块

  • #error 当遇到标准错误时,输出错误消息

  • #pragma 使用标准化方法,向编译器发布特殊的命令到编译器中

预定义宏

  • ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。

#include <stdio.h>
main()
{
   printf("File :%s\n", __FILE__ ); // 当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量。
   printf("Date :%s\n", __DATE__ ); // 当前时间,一个以 "HH:MM:SS" 格式表示的字符常量。
   printf("Time :%s\n", __TIME__ ); // 这会包含当前文件名,一个字符串常量。
   printf("Line :%d\n", __LINE__ ); // 这会包含当前行号,一个十进制常量。
   printf("ANSI :%d\n", __STDC__ ); // 当编译器以 ANSI 标准编译时,则定义为 1。
   printf("func :%s\n", __FUNCTION__ ); // 外部函数的名字
}

小心空格:

#define f (x) ((x)-1)

// 上述代码含义: f 代表 (x) ((x)-1)

上述代码,如果想定义f(x)((x)-1),则必须将f(x)中间的空格去除。

宏并不是函数,添加那么多的()是为了防止优先级错误:

#define abs(x) (((x)>=0)?(x):-(x))
#define max(a,b) ((a)>(b)?(a):(b))

宏并不是语句,assert断言的例子

if( x > 0 && y > 0 )
    assert( x > y);
else
    assert( y > x );

// 上述代码展开后,明显发现结构乱了

if( x > 0 && y > 0 )
    if(!(x > y)) assert_error("foo.c",37);
else
    if(!(y>x)) assert_error("foo.c",39);

宏不是类型定义:

#define T1 struct foo *
typedef struct foo *T2;

T1 a, b; // a 是指针, b是结构体
T2 c, d; // c,d都是指针