Elements of C Style

CS35: Programming and Problem Solving
Ray Ontko
Department of Computer Science
Earlham College

Good programs are readable by humans, not just readable by compilers. Programs are read and re-read during the development process, and useful programs are read by others who wish to extend, modify, and enhance them. Writing good programs, then, has much to do with writing programs that are easily understood by human readers.

Comment Header

Each program file should begin with an introductory comment. At the very least, each file should include a description of what is in the file, the name of the author, and the date of authorship. Any reader (including the author) who stumbles upon the file will immediately want to know "What is this?", "Who wrote this?", "When was it written?".

For example:

/*
average.c

This program reads a list of numeric grades from standard
input, and computes the count and average grade.  Any 
grades not between 0.0 and 100.0 are rejected.

Ray Ontko, 1999/10/05
*/

You may wish to include other information in this documentation header as well. Instructions on how to run the program, a history of changes that have been made to the file, and notes about what is broken are sometimes included.

Names

Name your functions and variables so that they clearly indicate what they do (functions) or hold (variables). In some cases, it may be appropriate to use short names like "i", "c", "x", or "y" to represent loop counters, characters read, or coordinate values, but use descriptive names where possible. "grade", "year", "distance", "principal", "rate", "months" are all preferable to "g", "y", "d", "p", "r", and "m". Choose names that make your programs and functions easier to read and understand.

If your function or variable name contains several "words", separate the words using the underscore character, or perhaps capitalize the first letter of each word. Surely "final_total" or "FinalTotal" is easier to read than "finaltotal".

Indentation

Indent your statements to indicate their level of nesting within the control structures of your program. "if", "else", "switch", "for", "while", and "do/while" statements are more readable if the statements which are conditionally executed are indented somewhat from the keywords of the control structure.

Be consistent in the degree to which you indent for each level of nesting in the control structure. By convention, C programmers indent in multiples of 2 or 4 spaces.

You should also make a choice and be consistent about whether you indent the "{" and "}" which define a block. For example:

main()
{
  float grade ;
  int count = 0 ;
  float total = 0.0 ;

  printf( "Enter grades, one per line, or CTRL-D to end.\n" ) ;

  while ( scanf( "%f" , &grade ) == 1 )
  {
    if ( ( grade < 0.0 ) || ( grade > 100.0 ) )
    {
      printf( "Must be between 0 and 100; try again.\n" ) ;
      continue ;
    }
    count ++ ;
    total += grade ;
  }

  if ( count > 0 )
  {
    printf( "Count = %d\n" , count ) ;
    printf( "Average = %.2f\n" , total / (float)count ) ;
  }
}

In the example above, note that each "{" is vertically aligned with the matching "}" of the block, and that all statements within each block are indented equally, and that all indents are multiples of the smallest indent (in this case, 2).

Horizontal Spacing

In addition to indentation, we can make the program easier on the eye by introducing spaces within lines. By inserting spaces within the line we can help the reader see each component, where that is desired. By leaving unnecessary spaces out, we can help the reader see patterns or groupings we wish to emphasize. For example:
    printf("Average = %.2f\n",total/(float)count);

    printf( "Average = %.2f\n" , total / (float)count ) ;

    printf( "Average = %.2f\n" , total / ( float ) count ) ;
The three statements above all do the same thing, but it might be argued that the first is too compressed, while the last is too spread out. Reasonable people might disagree over exactly which spaces should be inserted to achieve optimum readability, but all would agree that spacing can help guide the reader to notice what's important in the line.

Vertical Spacing

You can also use vertical whitespace to enhance the readability of your programs. Insert blank lines between groups of statements that are logically related. In a simple program, for example, you may wish to insert a blank line after your declarations, another after your initialization statements, another after your program reads its inputs, and another after the work is done before printing your outputs.

As with horizontal spacing, be judicious in your use of vertical whitespace; some is good, but more isn't necessarily better. Use it to help your reader see the "paragraphs" in your code.

Comments

In addition to the documentation header, your program should include other comments when appropriate. Each function you define ought to have an associated description, and some variables may require description beyond a simple name. If the behavior or purpose of a section of code is not obvious to the casual reader, you may wish to include some narrative about what's going on. You should not include a line-by-line commentary of your code, as a general rule.

As with all writing, be sure to use correct spelling, punctuation and grammar. Programs are hard enough to read without having to account for illiterate programmers.

Copyright © 1999, Ray Ontko (rayo@ontko.com).