Coding style

The main purpose of a coding style (or coding standard) is to ensure that the work of multiple contributors within a project (or a company) produces code that is uniform in style. That increases the readability of the code and makes it easier for others to update the code if/when that should become necessary. The styles vary from project to project and company to company so the first step when becoming a contributor/employee is to familiarize yourself with the coding style that the project/company uses.

A good coding style may also reduce coding errors, for example it’s easier to spot a missing brace when braces are always on a separaate line. In the end tho the code needs to be both syntactically and semantically correct and style alone doesn’t guarantee this. During compiling all style elements like indentation, multiple spaces, newlines and comments are removed.

Comments

Well placed comments make it easier to later find the right spot in the code for fixes/updates. Commenting also improves the readability of the code for others who happen to read your code or need to work with it. There should be at least 1 comment per 10 lines of code that explains what the code does.

There are several options for writing comments:

  • Single line comments
  • Inline comments
  • Multiline comments (see File Prolog)
  • Put a space after the comment symbols.
  • Pay attention to the length of the inline comment. If it’s too long then put it on a separate line or use a multiline comment.

In addition, we also use comments preceding the functions we make and for file headers. These comments are typically multiline comments.

File header

All .c and .h files should have a header that lists the name of the file, author(s), last modified date (or version) and the purpose of the code in the file. An URL or email address may be added as well.

Multiline comments are typically between the /* and */ symbols – everything in between is considered a comment.

Arithmetic and boolean operations

  • All operations that take 2 or more arguments should have spaces around the operator.
  • Unary operators should have no spaces between operator and preceding/following operand. For example !holiday (NOT holiday), ~a (INV a), k– (decrement k by 1).
An example of bad style:

Declaring and initializing variables

  • Variable names should indicate what they are for (self-explanatory).
  • Names should follow lowerCamelCase convention: first word is lowercase, every following word starts with uppercase.
  • Pointers and regular variables should be declared separately (on separate lines).
  • It’s possible to declare several variables of the same type with a single declaration, in that case variables should be separated by comma.
  • Initialization should be done only when declaring a single variable or on a separate line.
  • Avoid global variables.
An example of bad style:
  • First line: single letter variable names should be avoided, as their purpose is hard to understand later on and accidentally mixing them up is quite common. An reasonable exception to his would be naming loop counters and commonly understood names (e.g. n – number of objects)
  • Second line: Similar to first line, however it might even be more confusing as the names don’t relate to what the variables will most likely be storing.
  • Third line: Asterisk should be before the variable name when declaring pointers, not the data type. This is confusing because it may seem that both of the variables declared are pointers, however val is just an integer. Declaring pointer and non-pointer variables on the same line should be avoided in general.
  • Fourth line: It’s a mix of initialized and uninitialized variables. They should be declared on separate lines, as this is confusing and mistakes are prone to happen.
  • Fifth line: Even though the name seems descriptive, it is written in an unreadable mannter, as the word separation is not clearly visible. It should also be considered if this long variable names are reasonable.

#define preprocessor directives

  • Defines are used to avoid magic numbers in the code, amongst other things
  • Defines are in FULL_UPPERCASE. If the name consists of several words then underscore is used to separate them.
An example of bad style
  • In the first example, the macro definition may be mistaken to a variable declaration. This may cause confusion later, as you may try to change this value, however cannot.
  • The second example has bad readability as the word separation isn’t clearly visible.

Indentation

  • Indentation helps to improve the readability of the code. Indented blocks of code make it easier to locate the part that needs changing whether by yourself or by others.
  • Indentation means that all lines in a block have 4 (additional) spaces at the start. Typically a tab character is used.
  • In most cases the contents of braces are indented.
  • Indentation helps when several loops or conditions are mixed by giving a visual overview where a certain block ends and also helps with inserting the braces at the right part of the code.
  • Recommendation: try to indent the code as you type. Most IDEs indent for you as soon as you type { and hit Enter.
  • Recommendation: type both { and } and then write the code between them, this way you won’t forget to add the ending brace at the correct spot.

An example of bad style:

Line length and breaking lines

A line should not be longer than 80 characters. This provides better readability and improves compatibility with other platforms.

IDEs provide visual clues as to when a line is over lenghth.

Geany: Edit -> Preferences -> Editor -> Display
Choose Long line marker: Enabled and Column: 80

Code::Blocks: Settings -> Editor -> Margins and caret
Choose right margin hint: either visible line or highlight and Column: 80

In the example the line length is kept shorter than 80 characters. Use indent after the line break for the duration of the statement. When breaking text use ” at the end of the line and another ” at the start of the text next line. For regular statements no additional symbols are necessary.

An example of bad style:

Conditionals

  • Opening and closing braces should be on separate lines.
  • Content of the braces is indented.
  • There is a single space between if and (.
  • Generally there is a single space between all statements that are followed by brackets with the exception of functions.
    This doesn’t apply to main() and self-made functions!
  • Comparison and logical operators are surrounded by spaces. (See arithmetic operations)

Switch

  • There is a space after switch.
  • There is a space after case.
  • The contents of switch are indented.
  • The contents of each case are indented once more.
  • Don’t forget break statements.

Loops

  • Statements while and for are followed by space.
  • Braces are on separate lines.
  • The contents of braces are indented.
  • In the for statement there should be a space after each semicolon.

Functions

main() function
või
  • Use first style when you don’t intend to pass any parameters to your program from command line (console, terminal).
  • Use the second style if you DO intend to pass additional parameters (like filenames, switches, etc).
Self-made functions
  • The function name should explain the purpose of the function.
  • All words in the name are concatenated.
  • CamelCase convention is used for naming the functions. This makes functions distinctive from variables that use lowerCamelCase.
  • Each function should have a prototype either before the main() function or in the header file.
Function comments
  • A multiline comment should precede the function explaining what it does. The comment usually also details the arguments and return value and any possible side-effects the function may have (if any).
Standard comment
  • Description – states the purpose, limitations and the workings of the function. Any data altered that’s not local to the function must also be specified (e.g. arrays).
  • Parameters – their names, data types and semantics (what are they used as in the function). Any requirements for the values passed should also be specified!
  • Return value – data type and semantics
Shortened form
  • Shortened form should only be used for very basic functions.

 

Function prototypes
  • You should make a prototype for each of your functions.
  • Naming convention is the same as for functions.
  • Both type and name should be listed for parameters.
  • Prototypes of your functions should be listed in a separate header file (recommended) or in the .c file after the preprocessor directives (#include, #define).