-
lower underscore function names
void my_function_name(void)
-
Lower camel case variables
int myVariable = 10
-
Lower case underscore structs and enums custom types ending in
_t
typedef struct { int length; char* name; } my_struct_t;
-
Name macros and defines with all caps and underscores
#define MY_MACRO(x) ((x) + 1)
#define MY_DEFINE (10)
-
Surround defines with parens
#define MY_DEFINE (10)
-
Use of global variables should be reduced to minimum
- Use accessors where global values are needed
-
Number with specific importance should be abstracted to named defines for clarity (no magic numbers)
-
Make as much as you can static, use a prefix of g for static variables
static int gMyStatic = 10
- group common static values into a struct for easier debugging
-
Use standard int types when ever size is important, never imply a size
- uint32_t | uint16_t | uint8_t ...
-
Use do while for multi-line macros
-
Name so that the begining of the name stays consistent
/* WRONG */ void tx_send(void); void rx_send(void); /* CORRECT */ void send_tx(void); void send_rx(void);
-
Breakdown code into common logical files
- if file breaks ~1k lines it should probably be refactored to more than one file
-
File names are lower case dashed
super-awesome-file.c
-
Use header and source templates
-
All numbers with specific imporatance (magic numbers) should be defines
-
Defines use all caps and underscores
#define THIS_IS_A_DEFINE (12312)
-
typedef and enums are all lowercase with underscores and _t at the end
-
All enum values are all caps with underscores like defines
-
Explicitly define enum values for an externally used enums
typedef enum { FOO_FIRST = 1, FOO_SECOND = 2, FOO_THIRD = 3, } foot_enum_t;
- Use common naming for externed functions of the same file
/* in timer.c */
void timer_start(void) ...
void timer_stop(void) ...
- Static functions should use the most descriptive name
- Does not need to be prefixed with file name
- Return as soon as possible
- Do not use a space between function and parens
void my_function(void)
- Function should always return a status code if there is a failure mode
- Always use common error code enums over integers
- Function parameters should use enums over booleans for readability with complete functions
void timer_create(uint32_t period, enable_t enable);
...
timer_create(1000, ENABLED);
-
Bracket starts on the next line after declaration
/* BAD */ int badFunction (bool shouldDo, int *pointer) { if (!shouldDo) return 0 *pointer = value; return -1; } /* Good */ int myFunction(do_t do, uint8_t *pointer) { if (pointer == NULL) { return ERR_PARAM; } if (do == DO_NOTHING) { return ERR_NONE; } *pointer = 0x123123; return ERR_NONE; }
-
Opening bracket at the start of the next line
-
Avoid !, use == false to be more explicit
-
Favor positive logic
-
Avoid double negatives
/* bad */ if (UNSECCESSFULL != true)...
-
if else statements must always have braces
-
Never use
GOTO
-
Always use default in switch statements
-
Only use brackets in case statement if variables are introduced
-
Always comment fall through case statements
if (something == true) { foo++; bar--; } if (another == false) { return ERR_PARAM; } switch (x) { case 1: puts("one was hit"); break; case 2: puts("two was hit"); /* intentional fall through */ case 3: puts("two or three was hit"); break; default: puts("default"); }
- Use c99 style definitions for loop variables
for (int i = 0; i < 10 ; 1++)
{
prints("%02d-", i);
}