Skip to content

Instantly share code, notes, and snippets.

@deriamis
Last active April 23, 2017 03:45
Show Gist options
  • Save deriamis/5032d7ed6f0bfcdf824d6bb9decf1eff to your computer and use it in GitHub Desktop.
Save deriamis/5032d7ed6f0bfcdf824d6bb9decf1eff to your computer and use it in GitHub Desktop.
C Style Guide
// Sample file demonstrating my C coding style.
//
// Based on:
// https://gist.github.com/davidzchen/9187878
//
// General rules:
// - Indents are four spaces. No tabs should be used anywhere.
// - Each line must be at most 80 characters long.
// - Comments can be // or /* but // is most commonly used.
// - File names should be lower_case.c or lower-case.c
/*
The general idea here is to make the style help us to visually identify the
components of our code and promote readability. It is *deliberately*
inconsistent with itself to prevent the eye from scanning over potentially
incorrect code. It also assists self-documentation and therefore requires
work to do correctly, so don't cut corners with it. We're only using style
to highlight possible semantic errors here. The compiler is used to catch
the syntax errors.
*/
#include <stdlib.h>
#include <stdbool.h>
// For macros, use ALL_CAPS separated by underscore:
#define FLAG_FOO 0x0
// If a macro's replacement is not just a literal, enclose it in parentheses:
#define FLAG_BAZ (0x1 << 3)
// For constants, use k followed by PascalCase:
const int kStateFoo = 0;
// Enums should look like macros (because their values have no type)
typedef enum {
MODE_FOO,
MODE_BAR,
MODE_BAZ,
MODE_QUX
} Mode;
// Don't use _t to signal types. That's what the starting uppercase is for.
typedef enum {
STATE_FOO,
STATE_BAR,
STATE_BAZ,
STATE_QUX
} State;
// Names of members of structs are pascalCase starting with a lowercase letter.
// The type names and variable names should be aligned with each other.
typedef struct {
int this,
char that,
long other
} Example;
// Self-referential types should have a forward-reference typedef. Pointers
// should have their * in the column to the left for easy identification. Do
// not hide pointers in typedefs, but DO hide the implementation of self-
// referential data types in your .c files! Don't use _p to signal pointers,
// either. Type names should be PascalCase with initial capitals, and forward
// references should use the same name as the referent.
typedef struct Sample Sample;
typedef struct Sample {
int firstField;
bool secondField;
Mode mode;
State state;
Sample *next;
};
// Function names are PascalCase. Opening braces come at the beginning of the
// line after the function declaration. Arguments are lower_case separated by
// underscores.
bool SampleEqual(Sample *self, Sample *other_thing)
{
// Local variables are lower_case and separated by underscores.
if ( self == NULL && other_thing == NULL ) {
return true;
}
// All conditional blocks are surrounded by braces. The parentheses
// surrounding the logic statement should be separated from the statement by
// spaces.
if ( self == NULL || other_thing == NULL ) {
return false;
}
// For statements that span multiple lines, break after the logical operator
// and align each line with the start of the first line. The ending
// parenthesis for the logic statement should be on the next line, with the
// opening brace on the same line. Align the logical operators.
if (
self->first_field == other_thing->first_field &&
self->second_field == other_thing->second_field &&
self->state == other_thing->state &&
self->mode == other_thing->mode &&
self->next == other_thing->next
) {
return true;
}
// If the previous block ends with a return (or break or continue), do not
// follow it with an else.
return false;
}
// For function declarations that span multiple lines, use a combination of the
// forms for multi-line conditionals and structs. Avoid this!
Sample *SampleNew
(
int first_field,
bool second_field,
Mode mode,
State state,
Sample *next
) {
Sample *sample = (Sample *)malloc(sizeof(*sample));
if ( sample == NULL ) {
return NULL;
}
memset(sample, 0, sizeof(sample));
sample->first_field = first_field;
sample->second_field = second_field;
sample->mode = mode;
sample->state = state;
sample->next = next;
return sample;
}
Sample *SampleClone(Sample *sample) {
if ( sample == NULL ) {
return NULL;
}
// For function calls that span multiple lines, create a block with parens.
return SampleNew(
sample->first_field,
sample->second_field,
sample->mode,
sample->state,
sample->next
);
}
// For function declarations (and function calls) where you cannot fit
// the parameters with the first after the opening parentheses, then align
// the parameters indented four spaces on the next line. Avoid this!
static void SampleDoSomethingWithALongName
(
Sample *sample,
int parameter_with_a_long_name,
bool another_parameter,
int yet_another_parameter
) {
if ( sample == NULL ) {
return;
}
// Do not hug else and else-if with braces
bool local_variable;
if ( parameter_with_a_long_name == kStateFoo ) {
local_variable = true;
}
else {
local_variable = false;
}
sample->first_parameter += another_parameter;
sample->second_parameter |= local_variable;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment