跳到主要内容
🔍

代码示例:1.3.10 API 封装与工程目录规范

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

  • examples/ex1-rb.c · ring buffer 模块 API 封装(.h 声明 + .c 实现 + 使用方,三文件真实编译链接)

    /* ex1-rb.c —— ring_buffer 模块实现(1.3.10)
     * 模块内部细节对使用者隐藏:仅 ex1-rb.h 的声明是公开 API;内部辅助函数用 static 限定。
     * 编译(本文件与使用方一并编译链接):
     *   gcc ex1-rb.c ex1-main.c -o ex1 -std=c11 -Wall -Wextra -Wpedantic
     */
    #include "ex1-rb.h"
     
    static size_t rb_tail_index(const ring_buffer *rb)
    {
        return (rb->head + rb->count) % RB_CAPACITY;
    }
     
    void rb_init(ring_buffer *rb)
    {
        rb->head = 0;
        rb->count = 0;
    }
     
    int rb_push(ring_buffer *rb, int value)
    {
        if (rb->count >= RB_CAPACITY) {
            return -1;
        }
        rb->data[rb_tail_index(rb)] = value;
        rb->count++;
        return 0;
    }
     
    int rb_pop(ring_buffer *rb, int *out)
    {
        if (rb->count == 0 || out == NULL) {
            return -1;
        }
        *out = rb->data[rb->head];
        rb->head = (rb->head + 1) % RB_CAPACITY;
        rb->count--;
        return 0;
    }
     
    size_t rb_count(const ring_buffer *rb)
    {
        return rb->count;
    }
     
    /* 模块自测:使用者编译后运行 rb_self_test() 即知模块是否自洽 */
    int rb_self_test(void)
    {
        ring_buffer buf;
        int v = 0;
        rb_init(&buf);
        if (rb_push(&buf, 10) != 0) return 1;
        if (rb_push(&buf, 20) != 0) return 2;
        if (rb_pop(&buf, &v) != 0 || v != 10) return 3;
        if (rb_count(&buf) != 1) return 4;
        return 0;
    }
     
  • examples/ex2-calc.c · 标准目录构建(calc 模块:obj/ 目标文件 + bin/ 可执行文件)

    /* ex2-calc.c —— calc 模块实现(1.3.10 ex2,标准目录演示)
     * 文件在真实工程中位于 src/calc.c,头文件在 inc/calc.h;
     * 本示例为适配验证脚本平铺到 examples/ 顶层,目录布局与命令见正文。
     */
    #include "ex2-calc.h"
     
    static int last_error = 0;
     
    int calc_add(int a, int b) { return a + b; }
    int calc_sub(int a, int b) { return a - b; }
    int calc_mul(int a, int b) { return a * b; }
     
    int calc_div(int a, int b)
    {
        if (b == 0) {
            last_error = 1;
            return 0;
        }
        last_error = 0;
        return a / b;
    }
     
    int calc_last_error(void)
    {
        return last_error;
    }
     
  • examples/ex3-multiple-definition.txt · 头文件放普通全局定义的后果(diagnostic:multiple definition 真实报错)

    # 1.3.10 ex3(diagnostic 讲解文本):头文件放普通全局定义 → multiple definition
    # 实验结构(本机实测,gcc 15.2.0):
    #   bad.h:  int shared_counter = 0;        ← 普通定义放进了头文件(错误示范)
    #   a.c:    #include "bad.h" → 定义了一份 shared_counter
    #   b.c:    #include "bad.h" → 又定义了一份 shared_counter
    #   链接:  gcc a.c b.c m2.c -o m2 -std=c11 -Wall -Wextra -Wpedantic
    # 真实报错(见 examples.yaml ex3 expected_output):
    #   multiple definition of \`shared_counter'; ... first defined here
    #   collect2.exe: error: ld returned 1 exit status
    #
    # 正确做法:
    #   1. 头文件只放声明:extern int shared_counter;
    #   2. 定义只放一个 .c:int shared_counter = 0;
    #   3. 或需要每翻译单元独立副本时用 static(内部链接,语义不同,见 1.3.5)
    #
    # 记忆点:头文件 = 接口契约(类型/宏/函数声明/extern 声明),不是变量的家。