I follow this guide to ensure that all C code I write for Fossil Logic is readable, maintainable, and consistent, supporting collaboration and long-term project stability.
1. General Principles
- I write code that is clear and self-explanatory.
- I prioritize readability over cleverness or brevity.
- I document my reasoning when code is non-obvious.
2. File Structure
- I include a clear header comment at the top of each file with its purpose, author, and creation date.
- I organize
#includedirectives logically:- Corresponding header for the file.
- Standard library headers.
- Project headers.
- I separate logical sections in the file with comment blocks.
3. Naming Conventions
- I use snake_case for variables and functions.
- I use UPPERCASE_WITH_UNDERSCORES for macros and constants.
- I give meaningful names that describe the purpose, avoiding abbreviations unless widely understood.
4. Indentation and Formatting
- I use 4 spaces per indentation level; tabs are avoided.
- I place opening braces
{on the same line as the statement or function. - I maintain consistent spacing around operators and after commas.
- I break long lines at logical points, typically 80–100 characters per line.
5. Functions
- I keep functions short and focused; ideally under 50 lines.
- I declare function prototypes in headers and define functions in implementation files.
- I group related functions together and use clear section comments.
6. Control Structures
- I always use braces
{}forif,else,for, andwhileblocks, even for single statements. - I maintain consistent indentation inside control blocks.
- I use early returns to reduce nested blocks and improve readability.
7. Pointers and Memory Management
- I use
NULLfor uninitialized pointers and check for null before dereferencing. - I clearly pair
malloc()/calloc()withfree()and document ownership rules. - I minimize pointer arithmetic and prefer clear, explicit operations.
8. Comments and Documentation
- I write comments that explain why, not what—code should be self-explanatory.
- I use block comments for sections and inline comments sparingly for complex logic.
- I maintain documentation in headers for public APIs, including parameter descriptions, return values, and error handling.
9. Error Handling
- I consistently check return values and propagate errors where appropriate.
- I define error codes or enums rather than using magic numbers.
- I document failure cases clearly.
10. Preprocessor and Macros
- I avoid unnecessary macros; prefer
constorinlinefunctions. - I guard headers with
#ifndef/#define/#endif. - I keep macro names unique and descriptive to avoid conflicts.
11. Testing and Debugging
- I write testable code with modular functions.
- I include assertions or logging for critical assumptions.
- I remove temporary debug code before committing, leaving optional debug flags if necessary.
12. Version Control Practices
- I ensure code compiles cleanly and passes tests before committing.
- I write descriptive commit messages that explain what and why.
- I follow project coding conventions consistently to reduce merge conflicts.