跳转至

6. 编译预处理

预处理发生在正式编译之前。命令都以 # 开头,不是 C 语句,末尾也不加分号。

6.1 文件包含

#include <stdio.h>     /* 通常从系统头文件目录查找 */
#include "my_math.h"   /* 通常先从当前工程查找 */

头文件里通常放类型定义、宏、常量和函数声明。为了防止同一个头文件被反复展开,要加包含保护:

#ifndef MY_MATH_H
#define MY_MATH_H

double mean(const double a[], int n);

#endif

#include 做的是原样插入文件内容。工程里包含头文件 .h,不要为了省事去 #include "file.c",否则源文件中的定义很容易重复。

6.2 条件编译

#ifdef DEBUG
    fprintf(stderr, "x = %d\n", x);
#endif

#if VERSION >= 2
    /* 新版本代码 */
#else
    /* 兼容代码 */
#endif

defined(NAME) 可以在 #if 中检查宏有没有定义。条件编译是在编译前决定某段代码留不留下;普通 if 则是在程序运行时选择,两者不要混在一起。

6.3 #pragma#line

#pragma 用来给编译器传一些额外指令,各家编译器不完全一样。课上重点是 #pragma pack(n):它会改结构体成员的对齐方式,用完要恢复,不然后面定义的结构体也会受影响。

#line 行号 "文件名" 修改编译器此后报告的逻辑行号和文件名,常用于代码生成工具,普通程序很少直接使用。

评论