View Kai Wetlesen's LinkedIn profileView Kai Wetlesen's profile
Table Of Contents

It is very important to use a consistent and readable coding standard when writing a program in any language. Readability is absolutely key. If your code isn't readable and your style is inconsistent, your instructor won't be able to read it, or your employer won't be able to maintain it. While that may sound like a great way to keep from getting fired it won't help you at all to maintain even your own code.

Readable code is good code. Readable code is debuggable code. You are not an island unto yourself, and neither is your code. Even if you were, you're only disabling yourself from truly understanding the structure of what's going on.

You'll notice that the code snippets in this article are highlighted. This is done to simulate what you would see in a modern text editor (like Sublime or ViM), namely highlighting language keywords. Notice that even text highlighting isn't a cure-all for foul coding styles.

In this article, I wish to make apparent to you why it is imperative to practice good style, both for yourself and for the person who has to read your code later who might very well be you! This article is not here to tell you to use this style or that, but to convince you that following a clean, readable coding style is very important.

To start, I'm going to show you an extreme example of bad coding style. The code is very simple, and in it's clean form isn't meant to confound you as the reader. Before you read on, read the below code segment and try to answer this question: "What is this code really doing?"

	void dumptofile(char *filename, int **matrix)     {
	   FILE *outfile =fopen(filename,"w") ;
	 int row, col, cols;
	  for (row=0;matrix[row];row++){
	for (col= 0, cols= *matrix[ row]; col <=cols; col++)
	  fprintf(outfile, "%d ", matrix[row] [col]);
	    fprintf(outfile, "\n");       }
	fclose(outfile); return; }
		
Bracing Style — Foundation for Logical Division

How long did you spend trying to figure out what this code's purpose is? Five seconds? More? As you can see, this code is hardly legible, even with syntax highlighting. While this code might be syntactically valid and compile, you might earn an F or a D grade if you turned this in for your assignment (or rather, you should). I can guarantee that if you committed code that looked like this at work you would get reamed by your boss (if he doesn't ream you then he isn't paying attention which is even worse). This candidate code sample might be considered a competitive entry for these people but would certainly piss off these people along with everyone else. Coding without style does a disservice to any person who might read your code. Worse yet, crappy coding style can lead to indeterminate results (if the syntax is even valid) as the compiler interprets your code literally, as you wrote it, with hidden errors and all. Let's examine what is wrong with this code.

First, the bracing style is chaotic. One can't easily tell where a code block begins or where it ends. It makes debugging more difficult, as function boundaries aren't clearly defined in a visual sense, nor are loop or if blocks. Pick a bracing style, then use it throughout all of your code! It doesn't matter what style you use, so long as it is clean, consistent, and readable. More on brace style later. Your employer or instructor might even insist on using a particular style, so use it! When afforded the choice, I generally prefer Allman style bracing (a component to an entire coding style), so let's begin to reformat this using Allman's brace convention.

	void dumptofile(char *filename, int **matrix)
        {
	   FILE *outfile =fopen(filename,"w") ;
	  int row, col, cols;
	  for (row=0;matrix[row];row++)
          {
	for (col= 0, cols= *matrix[ row]; col <=cols; col++)
        {
	  fprintf(outfile, "%d ", matrix[row] [col]);
	    fprintf(outfile, "\n");       
        }
          }
	fclose(outfile);  
        return;
        }
		

Back to Table of Contents

Indentation — Visually Enforced Structure

That's a small improvement. The chaos is slowly being resolved into a more readable format, but several things still need to be fixed. First, the style that we've only partially employed doesn't follow any spacing and tab standards, which are also part of the Allman standard. Proper indentation is very important. In addition to bracing, it helps the reader (including you!) effectively determine which lines of code are nested with each other. One can easily see what actions happen within a loop, or when some condition is true; leading to visibiity of where a possible bug might arise.

In Allman style code (aka BSD style), a block definition will be followed by it's opening brace on the next line such that the definition and the brace are at the same indent level. One indent is 4 spaces in size, but may be represented with a tab character so long as the tabbing is consistent for all indentation. Keep in mind that the use of tab characters as opposed to simple spaces can cause your code to appear very differently across editors! See below for an example.

CONTROVERSY ALERT: Tab prefererence is an oft-argued topic, with some very nerdy people starting fistfights over such nonsense. If you find yourself hitting the tab key, but the organization you work for requires spaces, look for ViM's "expandtab" option. VS Code users may use the "editor.insertSpaces" option. It is also worth noting that tab widths are adjustable in modern text editors.

Note: Indentation size is often a stylistic choice made at an organizational level. Some organizations may ask for an indent size of 2, 3, or even as large as 8 space characters! However, the key is consistency, consistency, and consistency!

We can see here in the that our code does not hold such a standard, so let's fix the tabbing.

        void dumptofile(char *filename, int **matrix)
        {
            FILE *outfile =fopen(filename,"w") ;
            int row, col, cols;
            for (row=0;matrix[row];row++)
            {
                for (col= 0, cols= *matrix[ row]; col <=cols; col++)
                {
                    fprintf(outfile, "%d ", matrix[row] [col]);
                    fprintf(outfile, "\n");       
                }
            }
            fclose(outfile);  
            return;
        }
		

Back to Table of Contents

Horizontal Spacing — Clarify Your Expressions

Now this is looking a lot better! You'll notice that your eyes can follow the code right down the indentations. But, there's still some issues with the compound expressions, such as within the loop conditionals. There should be consistent spacing around arguments to a binary operator, like an addition or equal sign, and after both semicolon and comma separators within block constructs such as loops and conditional statements. This should be done so that anyone can take a very fast glance at a line of code and know exactly which unitary entities are being operated on. Note, we don't space out bracketed notation, so as to reinforce to the reader that the bracket dereferenced expression is actually one entity.

Like many things, style guidelines are flexible in some cases. For example, style guidelines don't really define a practice regarding space between function/loop identifiers and around operations enclosed by parentheses. My general preference is to have no space between identifiers and opening parentheses and space around parenthetical expressions. However, both examples shown below are perfectly acceptable.

        /** My preference **/
        void function( int var, char *var2 )
        {
            if( var2[var] != NULL )
            {
                myfunction( var2[var] );
            }
        }

        /** Strict Allman style. Note, no space around **/
        /**       the parenthetical expression.        **/
        void function(int var, char *var2)
        {
            if (var2[var] != NULL)
            {
                myfunction(var2[var]);
            }
        }
		

Regardless, let's apply these concepts to our sample code block and space out these expressions.

        void dumptofile(char *filename, int **matrix)
        {
            FILE *outfile = fopen(filename, "w");
            int row, col, cols;
            for (row = 0; matrix[row]; row++)
            {
                for (col = 0, cols = *matrix[row]; col <= cols; col++)
                {
                    fprintf(outfile, "%d ", matrix[row][col]);
                    fprintf(outfile, "\n");       
                }
            }
            fclose(outfile);  
            return;
        }
		

Back to Table of Contents

Vertical Spacing — Separation of the Concepts

Great! This code is looking much cleaner and professional already! The reader can easily digest binary expressions, loop conditionals, and any function calls. However there's one final issue, and that is the issue of whitespacing. Whitespacing allows the reader to clearly establish logical divisions within a function block. For example, variable declarations should be separate from operative statements. In our example, I'll mention the fopen, for loop, and fclose as a concrete example.

CONTROVERSY ALERT: Preferences for both horizontal and vertical spaces are frequently topics of heated arguments, if not all-out wars. If an organization requires you style your code in some particular way, follow that guideline!

Each statement has a different conceptual task. Fopen flips open some file, the for loop cycles through some data and writes it, and the fclose has to get the file closed back up. Duh. What really should happen though is these statements should be spaced apart, so the reader can see the logical steps. In this very simplistic example it may seem trivial. But, when the program gets more complicated, spacing can make the difference between a successful implementation and a migraine. Let's add some whitespace.

        void dumptofile(char *filename, int **matrix)
        {
            FILE *outfile;
            int row, col, cols;

            outfile = fopen(filename, "w");

            for (row = 0; matrix[row]; row++)
            {
                for (col = 0, cols = *matrix[row]; col <= cols; col++)
                {
                    fprintf(outfile, "%d ", matrix[row][col]);
                    fprintf(outfile, "\n");       
                }
            }

            fclose(outfile);  

            return;
        }
		

Now I say! That's a very nicely formatted function! Immediately, we can look at it and know what the function does, how it does it, and where we can make improvements. Example, in the inner loop, we can combine the two calls to fprintf into a single call, allowing us to increase the efficiency. We could also adjust the function to use pointers instead of indices, allowing for faster memory traversal. All of these optimizations are easier to spot with nicely formatted code.

It's also easier to spot possible bugs and potential crash points. One potential bug being that cols is defined using the first element in the array. If the reader of the function didn't know this is how the stop condition is established, he'd run the risk running right off the end of the array in question. We can also see that, even if cols was correctly defined we'd have a potential off-by-one error with the <= comparison. I'll leave these possible fixes to you, the student, as an excercise for you to sharpen your skills.

Back to Table of Contents

Coding Styles

I would like to close this article by showing several different coding styles and standards that you can employ when writing code in C. Each style is commonly used in industry, and in some cases one style might be enforced by the employer or organization. These styles can also be adapted to other languages such as Perl, Java, C++, and other C derivatives. For more information, see Wikipedia's article on the topic, and especially refer to the references in the footer. The Linux Foundation's document on coding style is also worth your reading time.

Each style has it's pros and cons, so pick one that fits your eyes and needs the best. But, once you have made your choice, stay consistent within your application!

Kernhigan & Ritchie Style (K&R Style)
        /**  As presented in Kernhigan and Ritchie's  **/
        /** famous book "The C Programming Language". **/
        /** Allows for unbraced if/else conditionals. **/
        for (i = 0; i < num; i++) {

             if (i % 2) {
                 printf("%d is odd.\n", i);
                 fprintf(odds, "%d\n", i);
             }
             else
                 printf("%d is even.\n", i);
        }
		
1 True Bracing Style (1TBS)
        /** Derived from and very similar to K&R style.     **/
        /** Note: If/else and 1 line loops strictly braced! **/
        for (i = 0; i < num; i++) {

             if (i % 2) {
                 printf("%d is odd.\n", i);
                 fprintf(odds, "%d\n", i);
             } else {
                 printf("%d is even.\n", i);
             }
        }
		
Allman Style
        /** Named after Eric Allman. Often referred **/
        /** to as ANSI style for it's extensive use **/
        /** in documents defining ANSI C and ISO C. **/
        for (i = 0; i < num; i++)
        {
             if (i % 2)
             {
                 printf("%d is odd.\n", i);
                 fprintf(odds, "%d\n", i);
             }
             else
             {
                 printf("%d is even.\n", i);
             }
        }
		
Whitesmiths Style
        /** Used in the Whitesmiths C Compiler.  **/
        /** Popuarized by "Programmer's Guide to **/
        /** Windows" by Durant, Carlson & Yao.   **/
        for (i = 0; i < num; i++)
             {
             if (i % 2)
                 {
                 printf("%d is odd.\n", i);
                 fprintf(odds, "%d\n", i);
                 }
             else
                 {
                 printf("%d is even.\n", i);
                 }
             }
        /** Note:                                **/
        /** I personally despise this style and  **/
        /** strongly discourage it's use.        **/
		
GNU Style
        /** Popularized by Richard Stallman,     **/
        /** and is an offshoot of Whitesmiths.   **/
        /** Used extensively by GNU maintainers, **/
        /** but infrequently everywhere else.    **/
        for (i = 0; i < num; i++)
           {
             if (i % 2)
               {
                 printf("%d is odd.\n", i);
                 fprintf(odds, "%d\n", i);
               }
             else
               {
                 printf("%d is even.\n", i);
               }
           }
		
Return to Top

This website conforms to the XHTML 1.0 Strict standard published by W3. Read more...