-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Coding style guide (C)
Dword edited this page Dec 22, 2022
·
7 revisions
- Naming conventions
- Style Conventions
- Initialization
- Code and Const Correctness
- Memory Management
- Secure Coding
- Best Coding Practices
- Use well-descriptive and meaningful names for variables.
- Suggest the type of the variable if necessary.
- Make macro names unique. Avoid simple and common names like: MAX, MIN, AVG due to the fact they can conflict with other package names.
- Constants must use ALL_CAPS_WITH_UNDERSCORES (defines or const variables).
- Use
g_
for global variables, e.g.g_output_file
- Use
s_
for static variables local to a function, e.g.s_internal_map
- Use descriptive lower case names, separated by underscores, and ending in
_t
for typedefs. - Enums must use descriptive lower case names separated by underscores. The list of enums must use ALL_CAPS_WITH_UNDERSCORES.
Example:
Note: Do not add a comma on the last element.
typedef enum my_descriptive_enum_t { ENUM_VAL_1 = 1, ENUM_VAL_2 = 2 } my_descriptive_enum_t;
- Struct name and its values must use descriptive lower case names separated by underscores. Put all bit fields together so the compiler will assign the same chunk for all. Example:
typedef struct {
char * name;
unsigned int enabled:1;
unsigned int verbose:1;
} my_type_t;
- Every new method/function being created must use descriptive lower case names separated by underscores.
- Use lower case for new folders being created.
- Use snake case (
new_file.h
) for new files being created. - Use descriptive related prefix for new files, e.g.:
os_query_manager.h
- Use one line for each variable.
- Use indexes to initialize arrays related to an enumeration.
-
if
,for
,while
andswitch
are control flow sentences, no functions. Examples:- Conditionals:
if (ptr == NULL) { // Then-part } else { // Else-part } if (!is_null) { // Then-part }
- Loops:
for (int i = 0; i < MAX; ++i) { // Loop body } while (condition) { // Loop body } do { // Loop body } while (condition);
- Switch:
switch (value) { case 0: zero(); break; case 1: case 2: low(); // Fallthrough case 3: positive(); break; default: high(); }
- Put a white-space between the reserved word and the parenthesis, and between the parenthesis and the brace.
- The opening brace should be in the same line as the statement.
- Use the negation operator (!) with boolean types only.
- Do not indent the case statements inside a switch.
- Comment
Fallthrough
if you explicitly want the code falls-through, this will avoid compiler warnings. - Use white-spaces in every binary operation.
- Do not use white-spaces in unary operations.
- Use parentheses if and only if they are needed or suggested by the compiler.
- See also: C operator precedence.
- Functions should limit themselves to a single page of code due to the fact that each method represents a technique for achieving a single objective.
- Avoid using magic numbers. Declare and use a well descriptive macro or constant name instead.
- Lines must not be longer than 120 characters, so break out function declarations over multiple lines.
- Always initialize variables. gcc with the flag
-W
may catch operations on uninitialized variables, but it may also not. - Every pointer being declared must be initialized. If the value of it is not yet defined,
NULL
should be used. This will avoid future memory errors which, in most cases, are very tough to be found.
- Use
const
for any object whose value does not change. - Use
const
for parameters passed by value. - Return values must be checked to handle errors reasonably. System calls and library functions provide important information to the programmer via return values.
- Include the system error text for every system error message.
- Every dynamically allocated memory (using
malloc
for instance) must have an associated code to free this memory at some other point in the program. - Every call to
malloc
,calloc
orrealloc
must be checked to avoid using memory badly reserved.
A simple coding error can lead to a hacking threat.
- Pointers nullness should be checked always unless it's being used in an internal function where it's safe to dereference or when the caller ensures that the pointer is not null.
- When a pointer needs to be freed, always set it to NULL after freeing it. This will avoid double free errors.
Example:
free(x); x = NULL;
- Always use safe functions instead of insecure ones. This will prevent collateral issues like buffer overflows.
Insecure | Safe |
---|---|
strcpy | strncpy |
strcat | strncat |
strcmp | strncmp |
printf / sprintf | snprintf |
gets | fgets |
tmpfile / mktemp | mkstemp |
- A variable must be declared in the inner scope possible.
- Define functions either static or inline if their purpose is to be used only in the .c file.
- Always use defensive programming, checking all values/content before using them, array limits, etc.