C Programming/Structure and style

From Wikibooks, open books for an open world
Jump to: navigation, search
Previous: Compiling Index Next: Variables

C Structure and Style[edit]

This is a basic introduction to good code style in the C Programming Language. It is designed to provide information on how to effectively use indentation, comments, and other elements that will make your C code more readable. It is not a tutorial on actually programming in C.

As a beginning programmer, the point of creating structure in the programs' code might not be clear, as the compiler doesn't care about the difference. However, as programs become complex, chances are that writing the program has become a joint effort. (Or others might want to see how it was accomplished.) Therefore, the code is no longer designed purely for a compiler to read.

In the following sections, we will attempt to explain good programming practices that will in turn make your programs clearer and more effective.

Introduction[edit]

In C, programs are composed of statements. These statements are terminated with a semi-colon, and are collected in sections known as functions. By convention, a statement should be kept on its own line, as shown in the example below:

 #include <stdio.h>
 
 int main(void)
 {
 	printf("Hello, World!\n");
 	return 0;
 }

The following block of code is essentially the same: while it contains exactly the same code, and will compile and execute with the same result, the removal of spacing causes an essential difference making it harder to read:

 #include <stdio.h>
 int main(void) {printf("Hello, World!\n");return 0;}

The simple use of indents and line breaks can greatly improve the readability of the code; without making any impact whatsoever on how the code performs. By having readable code, it is much easier to see where functions and procedures end, and which lines are part of which loops and procedures.

This book is going to focus on the above piece of code, and how to improve it. Please note that during the course of the tutorial, there will be many (apparently) redundant pieces of code added. These are only added to provide examples of techniques that we will be explaining, without breaking the overall flow of code that the program achieves.

Line Breaks and Indentation[edit]

The addition of white space inside your code is arguably the most important part of good code structure. Effective use of white space can create a visual scale of how your code flows, which can be very important when returning to your code when you want to maintain it.

Line Breaks[edit]

With minimal line breaks, code is barely readable by humans, and may be hard to debug or understand:

  1. #include <stdio.h>
    
  2. int main(void){ int i=0; printf("Hello, World!"); for (i=0; i<1; i++){ printf("\n"); break; } return 0; }
    

Rather than putting everything on one line, it is much more readable to break up long lines so that each statement and declaration goes on its own line. After inserting line breaks, the code will look like this:

  1. #include <stdio.h>
    
  2. int main(void)
    
  3. {
    
  4. int i=0;
    
  5. printf("Hello, World!"); 
    
  6. for (i=0; i<1; i++)
    
  7. { 
    
  8. printf("\n"); 
    
  9. break;
    
  10. }
    
  11. return 0;
    
  12. }
    

Blank Lines[edit]

Blank lines should be used to offset the main components of your code. Use them

  • After precompiler declarations.
  • After new variables are declared.

Based on these two rules, there should now be two line breaks added.

  • After line 1, because line 1 has a preprocessor directive
  • After line 4, because line 4 contains a variable declaration

This will make the code much more readable than it was before:

The following lines of code have line breaks between functions, but without indentation.

  1. #include <stdio.h>
    
  2.  
    
  3. int main(void)
    
  4. {
    
  5. int i=0;
    
  6.  
    
  7. printf("Hello, World!");
    
  8. for (i=0; i<1; i++)
    
  9. {
    
  10. printf("\n");
    
  11. break;
    
  12. }
    
  13. return 0;
    
  14. }
    

But this still isn't as readable as it can be.

Indentation[edit]

Many text editors automatically indent appropriately when you hit the enter/return key.

Although adding simple line breaks between key blocks of code can make code easier to read, it provides no information about the block structure of the program. Using the tab key can be very helpful now: indentation visually separates paths of execution by moving their starting points to a new column in the line. This simple practice will make it much easier to read and understand code. Indentation follows a fairly simple rule:

  • All code inside a new block should be indented by one tab[1] more than the code in the previous path.

Based on the code from the previous section, there are two blocks requiring indentation:

  • Lines 5 to 13
  • Lines 10 and 11
  1. #include <stdio.h>
    
  2.  
    
  3. int main(void)
    
  4. {
    
  5.     int i=0;
    
  6.  
    
  7.     printf("Hello, World!");
    
  8.     for (i=0; i<1; i++)
    
  9.     {
    
  10.         printf("\n");
    
  11.         break;
    
  12.     }
    
  13.     return 0;
    
  14. }
    

It is now fairly obvious as to which parts of the program fit inside which blocks. You can tell which parts of the program the coder has intended to loop, and which ones he or she has not. Although it might not be immediately noticeable, once many nested loops and paths get added to the structure of the program, the use of indentation can be very important. This indentation makes the structure of your program clear.

Indentation was originally one tab character, or the equivalent of 8 spaces. Research since the original indent size has shown that indents between 2 to 4 characters are easier to read[2], resulting in such tab sizes being used as default in modern IDEs. However, an indent of 8 characters may still be in use for some systems[3].

Comments[edit]

Comments in code can be useful for a variety of purposes. They provide the easiest way to set off specific parts of code (and their purpose); as well as providing a visual "split" between various parts of your code. Having good comments throughout your code will make it much easier to remember what specific parts of your code do.

Comments in modern flavors of C (and many other languages) can come in two forms:

//Single Line Comments  (added by C99 standard, famously known as c++ style of comments)

and

/*Multi-Line
Comments*/ (only form of comments supported by C89 standard)

Note that Single line comments are a fairly recent addition to C, so some compilers may not support them. A recent version of GCC will have no problems supporting them.

This section is going to focus on the various uses of each form of commentary.

Single-line Comments[edit]

Single-line comments are most useful for simple 'side' notes that explain what certain parts of the code do. The best places to put these comments are next to variable declarations, and next to pieces of code that may need explanation.

Based on our previous program, there are two good places to place comments

  • Line 5, to explain what 'int i' is going to do
  • Line 11, to explain why there is a 'break' keyword.

This will make our program look something like

#include <stdio.h>
 
int main(void)
{
    int i=0;                // loop variable.
 
    printf("Hello, World!");
 
    for (i=0; i<1; i++) {
        printf("\n");
        break;               //Exits 'for' loop.
    }
 
    return 0;
}

Multi-line Comments[edit]

Single-line comments are a new feature, so many C programmers only use multi-line comments.

Multi-line comments are most useful for long explanations of code. They can be used as copyright/licensing notices, and they can also be used to explain the purpose of a block of code. This can be useful for two reasons: They make your functions easier to understand, and they make it easier to spot errors in code. If you know what a block is supposed to do, then it is much easier to find the piece of code that is responsible if an error occurs.

As an example, suppose we had a program that was designed to print "Hello, World! " a certain number of lines, a specified number of times. There would be many for loops in this program. For this example, we shall call the number of lines i, and the number of strings per line as j.

A good example of a multi-line comment that describes 'for' loop i's purpose would be:

 /* For Loop (int i)
    Loops the following procedure i times (for number of lines).  Performs 'for' loop j on each loop,
    and prints a new line at end of each loop.
 */

This provides a good explanation of what i's purpose is, whilst not going into detail of what j does. By going into detail over what the specific path does (and not ones inside it), it will be easier to troubleshoot the path.

Similarly, you should always include a multi-line comment before each function, to explain the role, preconditions and postconditions of each function. Always leave the technical details to the individual blocks inside your program - this makes it easier to troubleshoot.

A function descriptor should look something like:

 /* Function : int hworld (int i,int j)
    Input    : int i (Number of lines), int j (Number of instances per line)
    Output   : 0 (on success)
    Procedure: Prints "Hello, World!" j times, and a new line to standard output over i lines.
 */

This system allows for an at-a-glance explanation of what the function should do. You can then go into detail over how each aspect of the program is achieved later on in the program.

Finally, if you like to have aesthetically-pleasing source code, the multi-line comment system allows for the easy addition of comment boxes. These make the comments stand out much more than they would without otherwise. They look like this.

 /***************************************
  *  This is a multi line comment
  *  That is nearly surrounded by a
  *  Cool, starry border!
  ***************************************/

Applied to our original program, we can now include a much more descriptive and readable source code:

#include <stdio.h>
 
int main(void)
{
    /************************************************************************************
     * Function: int main(void)
     * Input   : none
     * Output  : Returns 0 on success
     * Procedure: Prints "Hello, World!" and a new line to standard output then exits.
     ************************************************************************************/
    int i=0;                //Temporary variable used for 'for' loop.
 
    printf("Hello, World!");
 
    /* FOR LOOP (int i)
       Prints a new line to standard output, and exits */
    for (i=0; i<1; i++)
    {
        printf("\n");
        break;               //Exits 'for' loop.
    }
 
    return 0;
}

This will allow any outside users of the program an easy way to comprehend what the code functions are and how they operate. It also inhibits uncertainty with other like-named functions.

A few programmers add a column of stars on the right side of a block comment:

 /***************************************
  *  This is a multi line comment       *
  *  that is completely surrounded by a *
  *  cool, starry border!               *
  ***************************************/

But most programmers don't put any stars on the right side of a block comment. They feel that aligning the right side is a waste of time.

Comments written in source files can be used for documenting source code automatically by using popular tools like Doxygen[4][5]

Links[edit]

  1. Several programmers recommend "use spaces for indentation. Do not use tabs in your code. You should set your editor to emit spaces when you hit the tab key." [1] [2] Other programmers disagree. [3] [4] Regardless of whether you prefer spaces or tabs, make sure you keep it consistent with projects you are working on, because mixing tabs and spaces can cause code to become unreadable.
  2. [5]
  3. [http://lxr.linux.no/#linux+v2.6.31/Documentation/CodingStyle Linux Kernel coding standard
  4. "Coding Conventions for C++ and Java" "all the block comments illustrated in this document have no pretty stars on the right side of the block comment. This deliberate choice was made because aligning those pretty stars is a large waste of time and discourages the maintenance of in-line comments.",
  5. c2:BigBlocksOfAsterisks,"Code craft" by Pete Goodliffe page 82,Falvotech "C Programming Style Guide", Fedora Directory Server Coding Style
Previous: Compiling Index Next: Variables