跳到主要内容
🔍

代码示例:1.1.2 预处理指令深入

全部示例均标注编译命令、适用环境与实测状态;完整验证记录见《03.5-代码编译运行验证记录》。

  • examples/ex1-safe-macros.c · 安全宏演示(括号/do-while(0)/#与##/副作用)

    /* ex1-safe-macros.c —— 安全宏演示(1.1.2)
     * 适用环境:Linux / Windows(MinGW) 标准:C11(纯标准,无 GNU 扩展)
     * 编译:gcc ex1-safe-macros.c -o ex1 -std=c11 -Wall -Wextra -Wpedantic
     * 运行:Linux: ./ex1  Windows: ex1.exe
     */
    #include <stdio.h>
     
    /* 1) 对象宏(宏常量):纯文本替换,没有类型 */
    #define PI 3.14159
    #define MAX_BUFFER 256
     
    /* 2) 函数宏:每个参数和整体都要加括号(对比 BAD_SQUARE 反例) */
    #define SQUARE(x) ((x) * (x))
    #define BAD_SQUARE(x) x * x
     
    /* 3) 多语句宏:用 do { ... } while (0) 包裹,配合 if/else 使用也安全 */
    #define PRINT_PAIR(a, b) do { printf("%s = %d\n", #a, (a)); printf("%s = %d\n", #b, (b)); } while (0)
     
    /* 4) # 字符串化、## 标识符拼接 */
    #define STR(x) #x
    #define CONCAT(a, b) a##b
     
    /* 5) 副作用演示用:参数含 ++ 时会被求值两次 */
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
     
    int main(void)
    {
        int n = 5;
        int a = 3;
        int m;
     
        printf("PI = %f\n", PI);
        printf("SQUARE(5) = %d\n", SQUARE(n));
        printf("SQUARE(2 + 3) = %d\n", SQUARE(2 + 3));        /* ((2+3)*(2+3)) = 25 */
        printf("BAD_SQUARE(2 + 3) = %d\n", BAD_SQUARE(2 + 3)); /* 2 + 3*2 + 3 = 11 —— 反例 */
     
        PRINT_PAIR(n, SQUARE(n));   /* do-while(0):多语句宏,任何位置使用都安全 */
     
        printf("CONCAT(MAX, _BUFFER) = %d\n", CONCAT(MAX, _BUFFER));   /* → MAX_BUFFER → 256 */
        printf("STR(hello) = \"%s\"\n", STR(hello));                    /* → "hello" */
     
        m = MAX(++a, 0);            /* ++a 被求值两次:3 → 4 → 5 */
        printf("MAX(++a, 0) = %d, a = %d\n", m, a);
     
        return 0;
    }
     
  • examples/ex2-conditional-compile.c · DEBUG/RELEASE 条件编译(两遍编译输出不同)

    /* ex2-conditional-compile.c —— DEBUG/RELEASE 条件编译演示(1.1.2)
     * 适用环境:Linux / Windows(MinGW) 标准:C11
     * 两遍编译(输出不同,均已实测):
     *   gcc ex2-conditional-compile.c -o ex2-release -std=c11 -Wall -Wextra -Wpedantic
     *   gcc ex2-conditional-compile.c -o ex2-debug -std=c11 -Wall -Wextra -Wpedantic -DDEBUG
     * 运行:Linux: ./ex2-release / ./ex2-debug  Windows: ex2-release.exe / ex2-debug.exe
     */
    #include <stdio.h>
     
    #define VERSION "1.0.0"
     
    #ifdef DEBUG
    #define LOG(msg) do { printf("[DEBUG] %s:%d %s\n", __FILE__, __LINE__, msg); } while (0)
    #else
    #define LOG(msg) do { } while (0)
    #endif
     
    int main(void)
    {
        printf("version %s build\n", VERSION);
        LOG("进入 main");
        printf("正常业务输出\n");
        LOG("业务完成");
        return 0;
    }
     
  • examples/ex3-0b-diagnostic.c · 0b 二进制字面量标准归属演示(diagnostic)

    /* ex3-0b-diagnostic.c —— 演示:0b 二进制字面量不是 C11 标准(1.1.2,diagnostic)
     * gcc 15.2.0 实测(MinGW-w64):
     *   gcc ex3-0b-diagnostic.c -o ex3 -std=c11 -Wall -Wextra -Wpedantic
     *     → warning: binary constants are a C23 feature or GCC extension [-Wpedantic](仍能编译,exit 0)
     *   gcc ex3-0b-diagnostic.c -o ex3 -std=c11 -Wall -Wextra -Wpedantic -Werror
     *     → error: binary constants are a C23 feature or GCC extension [-Werror=pedantic](编译失败)
     *   默认模式(本机 gcc 15 默认 gnu23):0b 为 C23 标准语法,零警告
     * 结论(err-7.1-22):0b 不是 C99/C11 标准,是 GNU 扩展 / C23 特性;严格工程(-Werror)下等于不可用
     */
    int main(void)
    {
        int x = 0b1010;   /* GNU 扩展 / C23 二进制字面量;C11 没有 */
        (void)x;
        return 0;
    }