CS 211: C Style Manual

Compiler Warnings

  1. Your code compiles cleanly, without the compiler issuing any warnings (and this is not acheived by disabling the warnings we turn on for you in the provided Makefile).

Names

  1. Field (member variable) names are appropriately descriptive of what they stand for; names shouldn’t just reiterate the type. While concise names are best, long and understandable names are preferred over small and mysterious ones.
  2. Variable, constant, and function names are in lower_snake_case.
  3. “Small” structs and classes have lower_snake_case names, whereas “large” structs and classes have Upper_snake_case names.
  4. Preprocessor #defines are in SCREAMING_SNAKE_CASE.

Variables

  1. It’s better to define a variable with an initializer later than to define it uninitialized earlier and assign it later.
    Bad Better
    some_type* x;
    
    if (some_condition) {
        x = malloc(sizeof *x);
        if (x == NULL) exit(1);
        // use x in here
    }
    if (some_condition) {
        some_type* x = malloc(sizeof *x);
        if (x == NULL) exit(1);
        // use x in here
    }

Booleans

  1. Don’t compare a Boolean to another Boolean, because it already is a Boolean!
    Bad Better
    if (is_good(doggo) == true) {
    if (is_good(doggo)) {
    if (is_good(doggo) == false) {
    if (!is_good(doggo)) {
  2. Don’t use an if just to return a Boolean you already have.
    Bad Better
    if (a < b) {
        return true;
    } else {
        return false;
    }
    return a < b;
    if (is_good(doggo)) {
        return false;
    } else {
        return true;
    }
    return !is_good(doggo);
  3. When you need a Boolean, use bool literals true and false, not int literals 1 and 0. C automatically converts between the two types as needed, but bool makes your code clearer because it gives the reader a more precise idea what it’s for. (To get access to type bool and its literals in C, #include <stdbool.h>.)

Statements

  1. Use else along with if for a case whose condition is the opposite of the if condition. In particular, don’t check a condition and then its opposite in adjacent ifs.
    Bad Good
    if ( n % 2 == 0 ) {
        ⋮  //  even case
    }
    
    if ( n % 2 != 0 ) {
        ⋮  // odd case
    }
    if ( n % 2 == 0 ) {
        ⋮  //  even case
    } else {
        ⋮  //  odd case
    }
  2. Always use braces with if, while, and for statements. Leaving them out can cause easy-to-make but difficult-to-find mistakes when modifying code later.
    Bad Good
    if (test_cond())
        error_message();
    if (test_cond()) {
        error_message();
    }
    while (result)
        result = check_state();
    while (result) {
        result = check_state();
    }

Formatting

  1. Lines are no longer than 80 characters.

    You can use the grep(1) command to print out the lines in a file that exceed the limit. For example, to check every .c and .h file in the src directory, run % grep -nE '.{81,}' src/*.{c,h}

  2. Indentation is consistent and properly reflects code structure.
  3. Indentation is by four spaces; tabs are unacceptable because they do not display the same everywhere. (Note that this does not mean that you should avoid the Tab key—pressing Tab in Micro will correctly align the current line using spaces, not tabs.)
  4. Long blocks of code are separated into “paragraphs” using blank lines.
  5. Infix operators generally have space on both sides.
  6. Commas and semicolons have whitespace (a space or end-of-line) after but no space before.

Comments

  1. Each function, structure, class, or member created by you (as opposed to those already specified or declared in the starter code) has a comment above its declaration succinctly stating its purpose. (If something is declared multiple times, this comment appears only on its first occurrence, preferably in the header file.)
  2. Excessive comments that inhibit readability are avoided. Assume your reader understands the language; only explain the non-obvious.