This document outlines the standards and best practices for C development at Bayat.
- Follow the K&R style for code formatting
- Maximum line length should be 80 characters
- Use 4 spaces for indentation, not tabs
- Files should be encoded in UTF-8
- Files should end with a newline
- Comments should be written in grammatically correct English
- Use
/* */
for multi-line comments and//
for single-line comments
-
Functions:
- Use snake_case for function names (e.g.,
calculate_total
,find_element
) - Use descriptive names that clearly indicate the purpose
- Prefix module/component-specific functions with a component identifier (e.g.,
net_connect
,mem_allocate
)
- Use snake_case for function names (e.g.,
-
Variables:
- Use snake_case for variable names (e.g.,
item_count
,user_input
) - Use meaningful names that reflect the purpose or meaning
- Boolean variables should use
is_
,has_
, orcan_
prefixes (e.g.,is_valid
) - For loop counters or temporary variables, single letters like
i
,j
,k
are acceptable
- Use snake_case for variable names (e.g.,
-
Constants and Macros:
- Use SCREAMING_SNAKE_CASE for constants and macros (e.g.,
MAX_BUFFER_SIZE
,PI_VALUE
) - Don't use Hungarian notation
- Use SCREAMING_SNAKE_CASE for constants and macros (e.g.,
-
Structures and Typedefs:
- Use PascalCase for structure type names (e.g.,
NetworkConnection
,UserData
) - Use snake_case for structure members
- Use
_t
suffix for typedef names (e.g.,size_t
,net_conn_t
)
- Use PascalCase for structure type names (e.g.,
-
Enums:
- Use PascalCase for enum type names
- Use SCREAMING_SNAKE_CASE for enum values
- Prefix enum values with a common prefix (e.g.,
COLOR_RED
,COLOR_BLUE
)
-
File Structure:
- Header files should use
.h
extension - Implementation files should use
.c
extension - Place standard library includes first, then custom includes
- Use include guards in all header files using
#ifndef
,#define
, and#endif
- Separate logical code sections with comments
- Header files should use
-
Standard order for file content:
- Include directives
- Macro definitions
- Type definitions (structs, enums, typedefs)
- Function prototypes
- Global variables (minimize use)
- Function implementations
-
Allocation and Deallocation:
- Always check the return values of
malloc()
,calloc()
, andrealloc()
- Free all allocated memory when no longer needed
- Use a consistent memory management pattern throughout the codebase
- Consider implementing or using custom memory management routines for specific purposes
- Always check the return values of
-
Preventing Memory Leaks:
- Ensure that resources are released in all code paths, including error conditions
- Use tool support (Valgrind, AddressSanitizer) to check for memory leaks
- Document ownership and lifetime of allocated memory in function documentation
-
Buffer Management:
- Always check for buffer overflow conditions
- Prefer safer alternatives to unsafe functions (e.g., use
strncpy()
instead ofstrcpy()
) - Never use gets(), prefer fgets() with appropriate buffer size checks
-
Error Codes:
- Use consistent error codes across the application
- Return error codes from functions rather than using global error variables where possible
- Document all possible error codes a function can return
-
Error Reporting:
- Implement a consistent error reporting mechanism
- Consider using a logging system to record errors
- Handle errors at the appropriate level, avoiding error propagation when the error can be handled locally
-
Code Comments:
- Document the purpose of all functions in header files
- Document non-obvious implementation details in implementation files
- Use consistent comment style for API documentation
-
Function Documentation:
- Document all parameters, return values, and error conditions
- Specify any side effects or preconditions
- Format:
/** * Brief description of function * * @param param1 Description of first parameter * @param param2 Description of second parameter * @return Description of return value */
-
Unit Testing:
- Write tests for all public functions
- Use a consistent testing framework (e.g., Unity, CUnit)
- Test edge cases and error conditions
-
Integration Testing:
- Test interaction between modules
- Test with realistic data sets
-
Input Validation:
- Validate all input, especially user input
- Check array bounds before access
- Use secure coding practices to avoid common vulnerabilities
-
Secure Functions:
- Prefer secure alternatives to unsafe standard library functions
- Avoid functions prone to buffer overflows (gets(), scanf() without limits, etc.)
- Consider using security-focused static analysis tools
-
General Guidelines:
- Optimize for readability and correctness first, then performance
- Profile code to identify actual bottlenecks before optimizing
- Document performance-critical code sections
-
Algorithm Selection:
- Choose appropriate algorithms based on data size and usage patterns
- Consider space-time tradeoffs based on the application requirements
-
Library Usage:
- Prefer standard libraries when possible
- Document all external dependencies
- Consider portability when selecting libraries
-
Version Management:
- Specify compatible versions for all dependencies
- Test with the specific versions used in production
-
Portability:
- Use standard C (C99 or C11) for maximum portability
- Isolate platform-specific code in dedicated modules
- Use conditional compilation for platform-specific code (#ifdef)
- Document platform-specific assumptions
-
Endianness:
- Be aware of endianness issues when working with binary data
- Use appropriate conversion functions when necessary
-
Recommended Tools:
- Compiler: GCC, Clang
- Static Analysis: Cppcheck, Clang Static Analyzer
- Memory Checking: Valgrind, AddressSanitizer
- Formatting: clang-format
- Build System: Make, CMake
-
Compiler Warnings:
- Compile with high warning levels (e.g.,
-Wall -Wextra
for GCC) - Treat warnings as errors in CI/CD pipelines
- Compile with high warning levels (e.g.,
- Commit Guidelines:
- Follow the project's commit message format
- Group related changes in a single commit
- Ensure the code compiles and passes tests before committing