ARIN UPADHYAY | Embedded Systems & Low-Level C Developer
HOME | PROJECTS | BLOG | OTHER
29-08-2025
How I Code in C
C is one of my favorite languages, but it comes with a reputation: powerful, fast but dangerous if you're careless.
Over time, I've developed my own set of rules and habits that keep my C code safe, clean, and consistent.
This post is basically how I like to structure projects, name things, and enforce safety.
Naming Convention:
I keep naming dead simple and consistent across every project:
- snake_case: variables and functions
- PascalCase: types
- SCREAMING_SNAKE_CASE: preprocessors
Project Structure:
I hate messy include chains and header spaghetti, so I stick to a simple layout:
- common.h: my “universal” header. It has #pragma once, all config macros, typedefs, and stdint.h
- <module>.c: include common.h or module related .h/.c files
- main.c: entry point with the general algorithm. include common.h or related .h/.c files.
Safety Rules/Guide:
To avoid the classic “C pitfalls” and for easy remembering, I have simplified (or maybe oversimplified) the 10 rules from The Power of 10: Rules for Developing Safety-Critical Code by Gerard J. Holzmann.
In my opinion, this list should treated more like a optional checklist or a guide than a rulebook because not every application needs to be absolutely safety-critical but it never hurts to be more than less.
- No goto, recursion, or setjmp/longjmp (control and scope safety)
- Variables declared as local as possible (control and scope safety)
- Only one level of deref, no function pointers, no hidden deref (memory safety)
- No dynamic memory after initialization (memory safety)
- Check parameters and non-void return values (bounds and check safety)
- At least two asserts per function (bounds and check safety)
- Every loop must either have a clear upper bound or be provably non-terminating (bounds and check safety)
- Functions stay under ~60 lines (meta)
- Preprocessor for only headers and simple macros (meta)
- Clean pass compilation with all warnings, pedantic, and static analysis (meta)
Recommended:
- Arena allocators: a perfect fit for rule #4
- Dynamic arrays: flexible storage without manual reallocation boilerplate
- stb-style/header-only libraries: drop-in, minimal dependencies, easy to use
By keeping naming, structure, and safety consistent, I can open up a project months later and instantly feel at home in the code.