C Style Standards for ECE1011
(Last Mod: 04 November 2010 18:11:40 )
The largest single cost in the software industry is software maintenance - correcting, updating and improving existing software. To keep these costs under control, it is vital that people other than the original programmer be able to readily interpret a piece of code. One of the biggest steps to ensure this is to require each programmer to adhere to a common set of standards, known as programming style. Standardization is not limited to the software industry, imagine purchasing a replacement battery for your flashlight if all battery manufacturers did not adhere to common standards for terminal voltage and shape or physical dimensions.
If you have studied the material regarding Common C Pitfalls, you have already been exposed to most of the guidelines which make up this set of standards. The purpose of this section is to summarize these guidelines in one place. Be aware that there is no guarantee that the example code in this section will display or print on your particular browser correctly. So if the code does not appear to conform to the standards as described, contact the instructor for clarification. Also, the last section of the Pitfalls document also contains these standards.
If your code does not conform to these standards, it will not receive full credit. The fact that your code runs and produces the correct values will not influence this.
main() function declaration
Unless another format is applicable, the accepted default declaration for your main() function is:
int main(void)
This is the form you will be expected to use in this course.
main() function exit values
Since your main() is declared as an integer function, you are expected to return an integer value. While you will not be using these values, the values are returned to the operating system and could, in concept, be accessed and used by a program calling your program. This might be used, for instance, by an automatic grading program that runs your program and feeds it good data on one pass and bad data on another pass looking for the exit code issued by your program to signal that the bad data was trapped.
In this course, you are expected to use an exit value of '0' if your program runs and exits normally. You are expected to use non-zero exit values if your code is exiting in an abnormal fashion and you are expected to document at the top of your code what those values mean. For instance, if you are opening two different data files, a return code of 1 might indicate that the first file failed to open and a return code of 2 might indicate that the second code failed to open. A return code of 3 might indicate that the data file contained data values that you couldn't work with.
Variable Declarations
Variables should be declared at the top of the function in which they are used and must be declared prior to any executable code. While many C compilers permit variables to be declared at the beginning of a block of code, we will not get into the scope and duration of such variables. Furthermore, the version of ANSI C used in this course does not permit variable declarations after the first line of executable code.
Global variables
Global variables are bad. While seemingly convenient, they shatter the very principles that C was founded on - namely modularity and least privilege. Your code should not have any global variables. Global variables have there place in the field of programming, but most programs which you will write do not need them and they invite many problems. If you feel that a global variable is most appropriate (notice the use of the word 'appropriate' as opposed to the word 'convenient') for a particular use in one of your programs, you had best make a good case for that decision in the program documentation and do not be surprised when you still lose points. Hint: Do not use globals - at least in your final code.
Indenting
Code should be indented according to its level. This means that all statements that are controlled by a particular line of code should be indented more than the controlling line. The amount of each indent should be consistent, two spaces works well. Where braces are used, the open and close braces should be vertically aligned with the left of the controlling line with no text (including comments) directly between them. In other words, all statements contained in a brace-delimited block of code should be indented more than the braces. This makes the structure of the code very clear and allows for easier debugging since matching braces and the manner in which they nest is readily apparent.
Example:
#includes
Including a file for evaluation by the preprocessor should reflect a need for something contained in the file being processed and not a general laziness on your part that favors blasting the compiler with every header file you have ever used instead of learning which header files give you access to which functions. To both document why a particular header file is being used and to assist you in learning which header files are associated with which functions, you are expected to place the names of functions actually used in your code next to the #include directive. For example:
#definitions
You should use #define preprocessor directives liberally. Many hardcore programmers contend that hard coded numbers should never appear in the body of the code. This is because it is frequently the numbers that get changed as code evolves and the ability to change all of the related values throughout the code by simply changing a few #define statement is a compelling argument. We will be no where near this demanding in our standards, but any place where a user defined quantity which is constant throughout the code but which might change from one compilation to the next is an example of where a #definition is appropriate and where the grader will look more favorably upon your work if you use one. All #define labels should be all, or at least mostly, upper case.
Variable Names
Use meaningful variable names. As mentioned in the C Pitfalls document, there are certain conventions which have arisen concerning the naming conventions for generic variables. These are summarized below and you are expected to observe them. All variable names should be all, or mostly, lower case. The use of title case (capitalizing the first letter of each word) is a good means to make long variable names readily meaningful particularly if you do not wish to separate words with an underscore.
Letter at the beginning of the alphabet (particularly a,b,c,d) should be used for parameters, either integer but more commonly floating point.
Letters in the middle of the alphabet (particularly i,j,k,l,m,n) should be used for integer variables.
Letters at the end of the alphabet (particularly r,s,t,u,v,w,x,y,z) should be used for floating point variables.
The above conventions arise out of the common usage of these letters in mathematics and greatly lend to the readability of your code. Likewise, ignoring them invites misinterpretation of your code. This is not to say that reasonable deviations cannot be made. If, in your program, time is an integer value then it is perfectly reasonable to use t as the variable for this and to make it an integer. The same would be true if you are working in a 3-D space with integer values - the use of x, y and z as integers is perfectly reasonable in this case.
Comments
Document your code with ample comments. If you have organized your code well, selected truly meaningful variable names and #define labels and been consistent in their use, your code will be largely self-documenting and you can focus on adding comments where they are most effective. Where they are especially appropriate is any place where your are doing anything complicated or out of the ordinary. If you devise a little trick to increase program performance, you should comment this portion especially well.
Take note that the original ANSI C standards did not recognize the use of a double forward slash to indicate a comment that continues to the end of the present line. While most compilers quickly adopted this convention and while it is included in the ANSI standard for C++, it is not ANSI C compliant with all of the compilers you are likely to use. Therefore you are expected to use the /* and */ delimiters to define your comments.
Unused Code
Delete portions of code which serve no purpose. As you develop code from one project to the next, you will often find yourself commenting out sections of code which no longer apply. Do not leave this unused code in the final version since it tends to make reading the code quite difficult.
Functions
Use functions to keep your main() lean. Your main() function should be quite short, usually less than a page and often less than one screen length. The same is true for functions - your goal should be to have them small enough so that the entire function can be displayed on the screen at the same time. This will make reading, comprehending and working on the code much easier. The statements in main() should reflect the high level tasks which your code is implementing and should rely heavily on function calls to do the nuts and bolts work.
Your main() should be the first function in your program file and any other functions should appear below it. The function prototypes should appear above main() - usually immediately above it between any macro definitions and the main() declaration. The function prototypes should be in the same order that the function definitions are later in the file.