# C Language Pro

> 当用 C99/C11 写系统/嵌入式/高性能代码，或攻克内存管理、指针运算、POSIX 系统调用与 pthread 并发时使用；产出所有权清晰、零泄漏的 C 代码及 Makefile(-Wall -Wextra)、头文件守卫、单测与 Valgrind 干净输出；不适用于 C++/Rust、纯语法提问或无 C 工具链场景；触发词：C、malloc、free、指针、内存泄漏、段错误、Valgrind、pthread、嵌入式

- Skill: `findscripter/c-language-pro` (Agent Skill)
- Install (CLI): `npx skillmds@latest add findscripter/c-language-pro`
- Raw SKILL.md: https://api.skillmd.com/api/skills/findscripter/c-language-pro/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: findscripter (https://skillmd.com/u/findscripter)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/findscripter/c-language-pro

---

## 何时使用

- 用 C99/C11 写系统级、嵌入式或高性能代码，需要手动管理内存且零泄漏时使用。
- 攻克 malloc/free 配平、内存池、指针运算与数据结构、POSIX 系统调用、pthread 并发，或用 Valgrind/gdb 排查崩溃与泄漏时使用。
- 触发词：C、malloc、free、指针、内存泄漏、段错误、Valgrind、pthread、嵌入式、内存池。

不该用的边界：

- 任务是 C++/Rust 或其他语言 → 转 `cpp-modern-pro` / `rust-pro`，C 与现代 C++ 惯用法（RAII、智能指针）截然不同。
- 只是查基础语法（`for`/`struct` 怎么写）→ 直接给语法，不必启用本技能的体系化方法。
- 环境无 C 工具链（gcc/clang、make）或目标不允许 C → 不适用。
- 纯崩溃/核心转储深挖 → 见 `gdb-debugging-cli`；纯内存安全审计 → 见 `c-cpp-security-review`。

## 步骤 / 指令

```
1. 明确约束：目标平台与标准（C99/C11）、运行时（裸机/RTOS/POSIX）、内存预算、是否多线程、是否允许动态分配。
2. 内存所有权先行：为每块堆内存指定唯一 owner，约定谁 malloc 谁 free；接口注释写明所有权转移（caller-frees / callee-frees）。
3. 防御式编码：检查所有返回值——尤其 malloc/calloc/realloc、open/read/write 等系统调用；失败路径走统一清理（goto cleanup 惯用法）。
4. 嵌入式/受限场景：尽量用内存池或静态分配替代频繁 malloc；最小化栈使用，避免大数组与深递归。
5. 实现 + 测试同步：单测用 CUnit 或同类；为每个分配/释放对写覆盖。
6. 过质量门：-Wall -Wextra 零告警；clang-tidy 静态分析；valgrind --leak-check=full 必须 0 泄漏、0 非法读写。
7. 仅在热点处优化：先 perf/gprof 剖析定位，再考虑缓存友好布局、减少分配；不要凭感觉提前优化。
```

核心规则：

- 每个 malloc 必有对应 free——分配与释放成对设计，realloc 失败要保住原指针不泄漏。
- 检查所有返回值，特别是 malloc 返回 NULL；系统调用失败查 errno 并处理。
- free 后立即置 NULL，杜绝悬空指针与 double-free；不要 free 非堆指针。
- 用 static 分析（clang-tidy）+ 编译告警（-Wall -Wextra）当硬门禁；嵌入式下控制栈用量。
- 遵循 C99/C11；所有系统调用都要有错误处理。

## 示例

最小工程骨架与质量门（Makefile）：

```makefile
CC      = gcc
CFLAGS  = -std=c11 -Wall -Wextra -O2 -g
TARGET  = app

$(TARGET): main.o
	$(CC) $(CFLAGS) -o $@ $^

memcheck: $(TARGET)
	valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./$(TARGET)

tidy:
	clang-tidy main.c -- $(CFLAGS)

clean:
	rm -f *.o $(TARGET)
```

头文件守卫 + 清晰所有权注释：

```c
#ifndef BUFFER_H
#define BUFFER_H
#include <stddef.h>

/* 返回堆分配的缓冲区；所有权转移给调用方，须 buffer_free 释放。失败返回 NULL。 */
char *buffer_new(size_t n);
void  buffer_free(char *buf);

#endif /* BUFFER_H */
```

检查返回值 + 统一清理（goto cleanup 惯用法）：

```c
int load(const char *path, char **out) {
    int rc = -1;
    FILE *f = fopen(path, "rb");
    if (!f) return -1;                 /* 检查系统调用返回 */

    char *buf = malloc(4096);
    if (!buf) goto done;               /* 检查 malloc */

    if (fread(buf, 1, 4096, f) == 0) { free(buf); goto done; }
    *out = buf;                        /* 所有权交给调用方 */
    rc = 0;
done:
    fclose(f);
    return rc;
}
```

释放后置空，杜绝悬空指针 / double-free：

```c
free(p);
p = NULL;   /* 之后误用即 NULL 解引用而非 use-after-free */
```

典型请求样例（可直接当提示词）：
- 「实现一个无泄漏的动态字符串，附 Valgrind 验证」
- 「用内存池替换嵌入式代码里的频繁 malloc」
- 「为这段 C 代码补全所有 malloc/系统调用的错误处理」
- 「用 pthread 写一个生产者-消费者队列，无数据竞争」

## 注意事项

- 别忽略 malloc/realloc 返回 NULL；realloc 失败时旧指针仍有效，直接覆盖原指针会泄漏。
- double-free 与 use-after-free 是 C 的头号崩溃源——free 后立即置 NULL，且只 free 堆指针。
- 不要返回指向局部栈变量的指针；跨函数共享数据用堆分配并明确所有权。
- 嵌入式裸机慎用动态分配：优先内存池/静态缓冲，控制栈深，避免递归与大型 VLA。
- 多线程共享数据须加锁或用原子；pthread 资源（mutex/cond/thread）要配对销毁/join。
- 优化前先剖析（perf/gprof）定位真热点；-Wall -Wextra、clang-tidy、valgrind 三道门缺一不可。
- 输出不能替代环境内实测、编译与评审；缺关键约束（平台/标准/内存预算/线程模型）时先发问再动手。

## 互见

- requires：无。
- related：`cpp-modern-pro`（C++ 用 RAII/智能指针管理内存，与 C 手动管理形成对照，跨语言时切换）；`gdb-debugging-cli`（崩溃与核心转储深度调试，本技能聚焦写 C 本身，疑难现场转交它）；`performance-profiler`（系统化性能剖析与火焰图，深度调优转交它）。
- combines_with：`c-cpp-security-review`（对 C 代码做缓冲区溢出、整数溢出、内存安全专项审计，补足 Valgrind 之外的漏洞治理）；`bug-hunter`（定位指针/内存类疑难 bug）；`code-reviewer`（C 代码写完后做正确性与质量审查）。

---
采编自 sickn33/antigravity-awesome-skills（源技能 `c-pro`，MIT 许可）。

