Z
ZHANK
文件与预处理

预处理器与宏

#include/#define/#ifdef、宏函数陷阱、条件编译

预处理器与宏

预处理是编译的第一步——在真正编译之前,先做文本替换。#define 不是变量定义,是纯粹的文本替换

学完本章你将: 掌握 #include/#define/宏函数陷阱/#ifdef 条件编译。


#define 宏常量

c
#include <stdio.h>

#define PI 3.1415926
#define MAX(a, b) ((a) > (b) ? (a) : (b))  // 宏函数

int main() {
    double area = PI * 10 * 10;
    printf("面积:%.2f\n", area);

    int m = MAX(3, 5);
    printf("MAX(3,5) = %d\n", m);  // 5

    return 0;
}

宏函数的致命陷阱

c
#define SQUARE(x) x * x

// ❌ 展开后的意外
int result = SQUARE(2 + 3);
// 展开:2 + 3 * 2 + 3 = 2 + 6 + 3 = 11(不是 25!)

// ✅ 修复:参数加括号
#define SQUARE_SAFE(x) ((x) * (x))

// 💡 宏函数规则:每个参数加括号,整体也加括号
c
// ❌ 带副作用的宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int x = 5, y = 3;
int z = MAX(x++, y++);
// 展开:(x++ > y++ ? x++ : y++) — x 或 y 被加了两次!

⚠️ 现代 C 中,推荐用 static inline 函数替代宏函数,类型安全且无副作用。


条件编译

c
#define DEBUG

#ifdef DEBUG
    printf("调试:x = %d\n", x);  // 定义了 DEBUG 就编译这句
#endif

#ifndef VERSION
#define VERSION "1.0"  // 如果没定义则定义
#endif

#if defined(_WIN32)
    printf("Windows\n");
#elif defined(__linux__)
    printf("Linux\n");
#endif

预定义宏

c
printf("文件名:%s\n", __FILE__);
printf("行号:%d\n", __LINE__);
printf("日期:%s\n", __DATE__);
printf("时间:%s\n", __TIME__);