C Coding Style Guidelines

We expect you to follow the style rules below. These are rules that we find useful toward ensuring that code is readable and that it does what it is supposed to do in the expected place. Variants of these rules can be found in various on-line sources (below) that may be more detailed or may make arbitrary choices differently. These sources can be interesting reading because they sometimes justify their rules or have other smart tricks that you may wish to adopt.

  1. Write readable code.
    1. Clear thought leads to clear code.
      1. Wild, cascading conditionals often indicate unclear thought.
      2. But often, writing an unclear solution is a good first step toward understanding the problem.
    2. Use consistent indentation of blocks and function bodies.
      1. Use a proper editor (emacs, vi) that assists with indentation.
      2. Prefer to indent by 4 spaces. (set ts=4). (Sufficient for visibity, not so much to waste space.).
      3. Avoid using the indent command as a last step; it can undo any manual beautification.
    3. Use Braces; avoid loops and conditionals without them.
    4. Variable name length should be proportional to scope.
      1. But avoid globals where they are unnecessary: add function parameters, including "out" parameters.
    5. Wrap lines manually if needed, simplify with temporary variables if possible.
    6. Functions may not be longer than 35 lines (roughly a screenful)
      1. Conversely, functions should represent a reasonable unit of complexity or be reused frequently.
      2. Too many functions can waste a lot of space.
    7. Use parentheses for clarity, especially with bit operations.
  2. Write code that does not confuse the compiler or lead to inconsistent behavior.
    1. Initialize all variables; the compiler can help with this.
    2. Malloc and free in visible balance; remember to free if returning with an error.
    3. Annotate unmodified parameters with const.
    4. Annotate helper functions with static.
      1. And annotate methods intended to be used from outside with extern.
    5. Be clean with warnings. -Wall -Wno-write-strings
      1. Use -Werror for discipline, though warnings do not always indicate errors.
  3. Consistent style. For 216:
    1. k&r (not gnu) braces: opening brace on the same line as the conditional or function, for compactness.
    2. Capitalize Globals. (but avoid them in general; they are often forbidden in this class)
      1. ALL_CAPS for #defined constants.
    3. Use underscores for multi_word_variables, not CamelCase.
    4. Prefer post-increment to pre-increment: c++, not ++c.
  4. Use the proper construct.
    1. Use a for loop when initialization, comparison, and increment are appropriate. (not a while loop)
    2. Use loop control rather than break; if a loop should end by a condition.
      1. "infinite" loops should be used for actual infinite loops, not because the break condition is buried.
    3. Avoid continue
      1. "continue" is okay if quickly testing a simple case to short circuit the loop.
    4. Avoid hidden return statements.
      1. return at the end is okay.
      2. return at the beginning for erroneous input is okay.
      3. return in the middle of a loop is sketchy.
    5. Never copy-and-paste code. Always use a function. Add parameters if needed.
      1. Functions can have helpers, or accept a few arguments and supply defaults to back-end functions that take more arguments.
      2. You don't want to have to fix a bug twice.
    6. Use compound assignment operators when appropriate: a += 3;
  5. Comment reasonably.
    1. Describe the intent of a block of code.
    2. Describe the use of a variable where it is declared, if not obvious.
    3. Present an example of input being parsed.
    4. Note /* TODO: */'s as placeholders.
    5. Avoid describing what a line of code does;
      1. If the code is too complicated to be read on its own, simplify or split or rename variables.
      2. Instead describe the purpose of a line.
      3. Exception: functions that take obscure arguments can be explained, e.g., ioctl.
    6. All code must have some comments.
    7. Comments that recite what happens on a line of code ("now call the Foo function") are worse than useless.
  6. Follow universal convention
    1. #include <>, then #include "", then #defines, then data types, then globals, then prototypes, then code.
      1. #defines and #includes in the middle of the code are usually frowned upon.
    2. main() first or last. (I expect last, but first has its justification)
    3. Functions should have input parameters before out parameters.
  7. Save yourself
    1. assert() facts you believe to be true. e.g., that an object passed as a parameter has been initialized, length values are non-negative, pointers are not null.
      1. It is better to check for error with assert() than not at all. It's compact in the code, and if you truly believe odd errors shouldn't happen, safe.
      2. assert() can help with readability, mechanically exposing pre- and post-conditions more strongly than comments (which can become obsolete).
      3. NOTE, however, that aborting execution may be inappropriate for submitted tests. We likely expect an error message.

Sources

  • http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml (note: for C++)
  • http://www.pk.org/rutgers/notes/pdf/Cstyle.pdf "C Programming Style" Paul Krzyzanowski
  • http://www.cs.arizona.edu/~mccann/cstyle.html
  • http://books.openlibra.com/pdf/c_handbook.pdf
  • http://users.ece.cmu.edu/~eno/coding/CCodingStandard.html