c-guidelines
Skill1 starsChanged 4 months agoMITView on GitHub
Use when writing, reviewing, or designing C code (C17 or C23) where memory safety, integer handling, header and ABI design, FFI with Rust or C++, build flags, or tests matter.
In this repository30 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- blind-reviewSkill
- cpp-guidelinesSkill
- dast-staging-guidelinesSkill
- data-engineering-guidelinesSkill
- diagramming-guidelinesSkill
- java-guidelinesSkill
- jj-guidelinesSkill
- kotlin-guidelinesSkill
- lua-guidelinesSkill
- python-guidelinesSkill
- re-provenance-guidelinesSkill
- reverse-engineering-guidelinesSkill
- rust-guidelinesSkill
- sast-triage-guidelinesSkill
- scala-guidelinesSkill
- security-review-guidelinesSkill
- spark-guidelinesSkill
- spark-pyspark-guidelinesSkill
- spark-scala-guidelinesSkill
- sql-guidelinesSkill
- supply-chain-guidelinesSkill
- swift-guidelinesSkill
- technical-writing-guidelinesSkill
- terraform-guidelinesSkill
- tool-prioritySkill
- tutoring-guidelinesSkill
- typescript-guidelinesSkill
- unreal-guidelinesSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 2 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 8
Use this as the shared C language rubric for agents.
- Very specific: line 37
Keep the public struct layout stable.
- Very specific: line 38
Do not put bitfields, unions with unclear active members, or long double in a boundary struct.
- Very specific: line 41
Document string encoding (UTF-8, not NUL-terminated, or both) and who frees returned buffers.
- Very specific: line 43
Never let a longjmp or a C++ exception cross the boundary.
- Very specific: line 67
Use exact repo-native gates first: the documented make, cmake --build, ctest, or CI script.
- Distinctive: line 91
When reviewing, lead with severity-ranked findings.
- Distinctive: line 93
When implementing, make the smallest coherent change, add or update tests for error paths and boundaries, and record the exact build and …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
C Guidelines
Use this as the shared C language rubric for agents. Prefer repo-local conventions when they are deliberate and documented. Push back when they produce fragile code or undefined behavior. The compiler accepting code is not evidence that the code is correct.
Source Of Truth
- SEI CERT C Coding Standard: https://wiki.sei.cmu.edu/confluence/display/c/SEI+CERT+C+Coding+Standard
- ISO C17 (ISO/IEC 9899:2018) and the C23 working draft n3220: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
- MISRA C, only where the repo adopts it. Follow the adopted edition and its recorded deviations.
- The repo's compiler flags, language standard setting, and CI configuration. These decide which features are allowed.
Core Rubric
- Ownership: state in the header comment who allocates, who frees, and how long a pointer stays valid. Mark each pointer as borrowed or owned. Pair every
_createwith a_destroyor_freefunction. - Bounds: pass
(const uint8_t *data, size_t len)for binary data. Never rely on a trailing NUL for non-text data. Checklenbefore every read and write. - Integers: unsigned arithmetic wraps. Signed overflow is undefined behavior. Check before you add or multiply
size_tvalues. Use checked helpers such as__builtin_mul_overflowor a small portable wrapper. Beware integer promotion and mixed signed/unsigned comparison. - Strings: use
snprintfand a bounded copy that reports truncation. Never usestrcpy,strcat,sprintf, orgets. Do not usestrtokin library code. Usestrtok_ror manual scanning. - Errors: return an
intor enum status and write results through an out-parameter. Do not use magic return values such as-1orNULLfor two meanings. Seterrnoonly for libc-style APIs, and read it right after the failing call. - Const and restrict: use
conston every read-only pointer parameter. Userestrictonly when the non-aliasing contract is true and documented. - Opaque types: expose
typedef struct foo foo;in the header and define the struct in the.cfile. Callers then cannot depend on layout. - Linkage: mark every file-local function and object
static. Declare only the public API in headers. - Initialization: use designated initializers (
{ .len = 0, .data = NULL }). Zero-initialize structs that cross a trust boundary. - Enums and switches: handle every enumerator in a
switch. Keep-Wswitchactive and avoid adefault:that hides new values. Validate enum values that arrive from outside the program. - Headers: use include guards or
#pragma onceas the repo does. Make each header self-contained. Put no function definitions in headers exceptstatic inline. Wrap declarations in#ifdef __cplusplus extern "C" { #endif. Use<stdint.h>and<stdbool.h>types (C23 hasboolas a keyword). - Memory: use
calloc(n, size)or an overflow-checkedn * sizefor arrays. Do not use VLAs in library code. Check every allocation result. Set a pointer toNULLafterfreewhen the pointer stays in scope. State whether_free(NULL)is allowed (it should be). - Concurrency: use C11
<threads.h>,<stdatomic.h>, or pthreads as the repo does. Every shared mutable object needs one named lock or an atomic. A data race is undefined behavior. - Undefined behavior: know the classes. They are out-of-bounds access, use after free, double free, uninitialized reads, signed overflow, invalid shifts, null dereference, strict aliasing violations, misaligned access, and unsequenced modification. Find them with warnings, sanitizers, and tests, not by inspection alone.
- Smallest coherent diff. No drive-by reformatting, renames, or include reordering outside the change scope.
ABI And FFI Rubric
- Keep the public struct layout stable. Account for padding and alignment. Use fixed-width types, not
int,long, orboolin#[repr(C)]mirrors. - Do not put bitfields, unions with unclear active members, or
long doublein a boundary struct. - Version boundary structs: put
uint32_t sizeoruint32_t versionfirst, and only append new fields. - A callback takes a
void *user_datapointer. Document which thread calls it, whether it may call back into the library, and how longuser_datamust live. - Document string encoding (UTF-8, not NUL-terminated, or both) and who frees returned buffers. Memory must be freed by the allocator that created it. Export a
_freefunction for library-allocated buffers. - A header that mirrors Rust
#[repr(C)]types must match field order, sizes, and enum underlying types. Prefercbindgenoutput and compare it to the committed header. - Never let a
longjmpor a C++ exception cross the boundary. Rust panics must not unwind into C.
Anti-Slop Checklist
Reject or fix these generated-code patterns on sight:
malloc(n * sizeof(T))with an unchecked multiplication.strcpy,strcat,sprintf,gets, orscanf("%s")into a fixed buffer.- Casting away
constto silence a warning. - Ignoring the return value of
malloc,fopen,fread,snprintf, orpthread_*. intused for sizes, lengths, or indexes wheresize_tis correct.charused for bytes. Useuint8_torunsigned char.- Comparing a
size_tagainst a possibly negativeint. memcpyormemsetwith an unvalidated length, or on overlapping regions (usememmove).sizeof(ptr)wheresizeof(*ptr)or the array size was meant.- Magic numbers for buffer sizes with no named constant or check.
- Cleanup duplicated on every error path instead of one
goto cleanuplabel, or leaked on one path. - Comments that restate the code (
/* increment i */) instead of stating ownership, units, or invariants. - Public functions missing
staticwhen they are file-local. - A
#definemacro that evaluates its argument twice where astatic inlinefunction works. assertused for input validation.NDEBUGremoves it.
Verification
Use exact repo-native gates first: the documented make, cmake --build, ctest, or CI script. Do not install tooling speculatively. Use these only when the repo has them or the change justifies them:
- Compiler warnings:
-Wall -Wextra -Werror -Wconversion -Wshadow(also-Wformat=2 -Wstrict-prototypeswhen the repo allows). - Static analysis:
clang-tidy,cppcheck, or the compiler's-fanalyzer(GCC). - Runtime checks: build tests with
-fsanitize=address,undefined. Use ThreadSanitizer (-fsanitize=thread) orvalgrindfor threaded or leak questions. ASan and TSan cannot run in the same binary. - Tests: use the repo's framework (Unity, CMocka, Check, or plain
assertprograms). Cover error paths and boundary lengths (0, 1, max, max plus 1). - Fuzzing:
libFuzzeror AFL++ for parsers, when configured. - Rust-generated headers: regenerate with
cbindgenand diff the result against the committed header. Add a layout test (sizeof,offsetof) on both sides.
Adversarial Checklist
Push back when a change or suggestion hits these traps:
- Fixing a warning with a cast. A cast hides the conversion bug. Fix the type or add a range check.
- "It works with -O0." Optimizers exploit undefined behavior. Test at the release optimization level too.
- Using
NULLor-1as both error and valid value. Return a status code and use an out-parameter. - Sanitizer clean means safe. Sanitizers see only executed paths. Add inputs at length boundaries and fuzz parsers.
strncpyas a safestrcpy. It may leave the buffer unterminated and pads with zeros. Usesnprintfor a checked copy.- Freeing a pointer the library does not own. Across an FFI boundary, free only with the allocator that made the memory.
packedstructs to match a layout. Unaligned member access is undefined behavior on some targets. Use explicit padding fields and_Static_asserton size and offsets.- Callback invoked on an unknown thread. Without a documented thread,
user_dataaccess races. Require a thread contract or internal locking.
Output Contract
When reviewing, lead with severity-ranked findings. Put memory-safety and undefined-behavior defects before design and style. Give file and line evidence, the failing input or state, and the safer direction.
When implementing, make the smallest coherent change, add or update tests for error paths and boundaries, and record the exact build and test commands you ran.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

