Essential C Coding Style Guide: Rules for Clean, Consistent Code
This guide outlines comprehensive C coding style rules, covering indentation, naming conventions, whitespace, comments, function prototypes, variable declarations, structures, enums, control flow, macros, and documentation, with clear examples to help developers write clean, maintainable, and consistent code across projects.
General Rules
The most important rule when writing C code is to follow the surrounding style. When fixing existing code, keep the current style even if it differs from your personal preference.
Whitespace and Indentation
Use the C99 standard.
Indent with spaces, not tabs; four spaces per indentation level.
Place a single space between keywords and the left parenthesis (e.g., if (condition)).
Do not put a space between a function name and the left parenthesis.
int32_t a = sum(4, 3); /* OK */
int32_t a = sum (4, 3); /* Wrong */Naming Conventions
Variable names are lowercase with optional underscores (e.g., my_var).
Do not use leading double underscores or a single underscore; these are reserved.
Function names are lowercase with underscores; avoid camelCase.
Structure and enum names are lowercase with underscores; typedef names end with _t.
Enum members are uppercase.
/* Variable naming */
int32_t a; /* OK */
int32_t A; /* Wrong */
/* Function naming */
void my_func(void); /* OK */
void MyFunc(void); /* Wrong */
/* Structure typedef */
typedef struct {
char *a;
char b;
} my_struct_t; /* OK */Comments
Always use /* comment */ style, even for single‑line comments.
For multi‑line comments, start each line with * after the opening /*.
Place comments with a 12‑level (48‑space) indent; if the line is longer, align to the next 4‑space level.
/* Single line comment (OK) */
/*
* Multi‑line comment (OK)
*/
// Wrong: line commentFunctions
Provide a prototype in a header before the implementation.
Return type and any qualifiers appear on a separate line from the function name.
When returning a pointer, align the asterisk with the type (e.g., const char *my_func(void);).
Document each function with Doxygen comments, including \brief, parameters, and return value.
/* OK prototype */
void set(int32_t a);
/* Implementation */
int32_t foo(void) {
return 0;
}
/**
* \brief Sum two integers.
* \param[in] a First operand.
* \param[in] b Second operand.
* \return Sum of a and b.
*/
int32_t sum(int32_t a, int32_t b) {
return a + b;
}Variables
Declare all local variables at the top of a block, before any executable statements.
Group variables of the same type together.
Avoid declaring new variables after the first statement in a block.
void foo(void) {
int32_t a, b; /* OK */
char c; /* OK */
a = 5; /* First executable statement */
int32_t d; /* Wrong – declaration after code */
}Structures and Enumerations
Structure names are lowercase with underscores; typedef names end with _t.
All members are lowercase; enum members are uppercase.
Use C99 designated initializers for struct initialization.
typedef struct {
int32_t x; /*!< X coordinate */
int32_t y; /*!< Y coordinate */
int32_t size;/*!< Size */
} point_t;
point_t p = { .x = 4, .y = 5, .size = 10 }; /* OK */Compound Statements and Control Flow
Always use braces for if, else, for, while, and do…while blocks, even for a single statement.
Place the opening brace on the same line as the statement; the closing brace aligns with the start of the statement.
Indent the contents of the block by one level.
Include a default case in switch statements and indent break under the case.
if (c) {
do_a();
} else {
do_b();
}
switch (val) {
case 0:
handle0();
break;
default:
break;
}Macros and Preprocessor Directives
Define constants with macros; macro names are uppercase with optional underscores.
Wrap macro parameters in parentheses and protect the entire expansion with parentheses.
For multi‑statement macros, use do { … } while (0) to ensure safe usage.
#define MAX(x, y) ((x) > (y) ? (x) : (y)) /* OK */
/* Multi‑statement macro */
#define SET_POINT(p, x, y) \
do { (p)->px = (x); (p)->py = (y); } while (0)Doxygen Documentation
Use Doxygen comments ( /** … */) for files, structs, enums, functions, and variables.
Prefer \ over @ for Doxygen commands.
Document parameters with \param[in] or \param[out] and return values with \return.
Reference enum members with \ref.
/**
* \brief Point structure.
*
ote Used for 2‑D geometry.
*/
typedef struct {
int32_t x; /*!< X coordinate */
int32_t y; /*!< Y coordinate */
} point_t;
/**
* \brief Compute the minimum of two values.
* \param[in] x First value.
* \param[in] y Second value.
* \return Minimum of x and y.
*/
static inline int32_t min(int32_t x, int32_t y) {
return (x < y) ? x : y;
}Header and Source File Guidelines
Each file ends with a single blank line.
Header files contain a license comment, an include guard ( #ifndef … #define … #endif), and extern "C" guards for C++ compatibility.
Include standard library headers with angle brackets and project headers with quotes.
Expose only public symbols in headers; private symbols stay in source files.
Declare global variables in headers with extern and define them in a single source file.
/* template.h */
#ifndef TEMPLATE_HDR_H
#define TEMPLATE_HDR_H
#ifdef __cplusplus
extern "C" {
#endif
/* Public declarations */
extern int32_t global_counter;
#ifdef __cplusplus
}
#endif
#endif /* TEMPLATE_HDR_H */
/* template.c */
#include "template.h"
int32_t global_counter = 0; /* Definition */For the full set of rules and examples, see the original repository: https://github.com/MaJerle/c-code-style
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
