预处理器与头文件
概念说明
预处理器会在正式编译前先处理源码中的预处理指令。 最常见的预处理任务包括头文件包含、宏替换和条件编译。
头文件的作用是共享声明。
一个更像样的 C 项目通常会把函数声明、结构体声明和宏定义放进 .h 文件,再把具体实现放在 .c 文件中。
预处理并不等于“只是 include 一下”。 它还会影响代码组织、调试信息输出、平台适配和编译开关控制,所以是 C 工程基础里非常关键的一部分。
语法/规则
#include <stdio.h>常用于包含标准库头文件,#include "my.h"常用于包含项目自己的头文件。#define会进行文本替换,编写宏时通常要给参数和整体表达式补括号。- 函数式宏适合非常短小的表达式封装,但带副作用的参数要格外谨慎。
- 常见预定义宏有
__FILE__、__LINE__、__DATE__、__TIME__。 - 条件编译常见写法有
#if、#ifdef、#ifndef、#elif、#else、#endif。 defined可用于配合#if检查某个宏是否已经定义。- 头文件应加保护宏,避免被重复包含;必要时也可以用
#error在配置不满足时直接阻止编译。
示例
| |
| |
| |
输出结果:
| |
常见错误
- 头文件没有保护宏,被重复包含后出现重复定义问题。
- 宏没有加括号,例如
#define SQUARE(x) x * x,在复杂表达式里结果会出错。 - 把大量实现代码直接塞进头文件,导致多文件编译和链接变得混乱。
- 用条件编译控制平台差异时没有把分支写完整,结果某些环境下直接编译不过。
- 在宏参数里传入带副作用的表达式,却没有意识到宏展开可能导致重复求值。