Now that we have covered the basic concepts of C programming, we can briefly discuss the process of compilation.
Compilation is basically translation a computer program called the compiler takes our C source code and translates it into the binary language used by computers. Of course, it is more complicated than that; but the basic idea applies.
To those new to programming, this seems fairly simple. A naive compiler might read in every
source file, translate everything into machine code, and write out an executable. This could work but
has two serious problems. First, for a large project, the computer may not have enough memory to
read all of the source code at once. Second, if you make a change to a single source file, you would
rather not have to recompile the entire application. To deal with these problems, compilers break
their job down into steps; for each source file (each .c file), the compiler reads the file, reads the
files it #includes, and translates it to machine code. The result of this is an "object file" (.o).
Once every object file is made, a "linker" collects all of the object files and writes the actual
program. This way, if you change one source file, only that file needs to be recompiled and then the
application needs to be relinked.
has two serious problems. First, for a large project, the computer may not have enough memory to
read all of the source code at once. Second, if you make a change to a single source file, you would
rather not have to recompile the entire application. To deal with these problems, compilers break
their job down into steps; for each source file (each .c file), the compiler reads the file, reads the
files it #includes, and translates it to machine code. The result of this is an "object file" (.o).
Once every object file is made, a "linker" collects all of the object files and writes the actual
program. This way, if you change one source file, only that file needs to be recompiled and then the
application needs to be relinked.
Without going into the painful details, it can be beneficial to have a superficial understanding of the compilation process, and here we will briefly discuss it:
Preprocessor
In this stage the "preprocessor directives" are dealt with. These include #includes, macros, and #pragma compiler settings. The result of the preprocessor is a text string.
Syntax Checking
This step ensures that the code is valid and will sequence into an executable program.
Object Code
The compiler produces a machine code equivalent of the source code that can then be linked into
the final program. This step ensures that the code is valid and will sequence into an executable
program.
the final program. This step ensures that the code is valid and will sequence into an executable
program.
Linking
Linking combines the separate object codes into one complete program by integrating libraries and
the code into the final executable format. ← Compilin |Error handling →
the code into the final executable format. ← Compilin |Error handling →
C Structure and Style
This is a basic introduction to producing effective code structure 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
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.
New programmers will often not see the point in following structure in their programs, because they often think that code is designed purely for the reading by a compiler. This is usually not the case, as wellwritten code that follows a welldesigned structure is usually much easier for programmers (who haven't worked on the code for months) to read, and edit.
In the following sections, we will attempt to explain good programming techniques that will in turn make your programs more effective.
Introduction
The following two blocks of code are essentially the same: Both of them contain exactly the same
code, and will compile and execute with the same result; however there is one essential difference.
code, and will compile and execute with the same result; however there is one essential difference.
Which of the following programs do you think is easier to read?
#include <stdio.h>
int main()
{printf("Hello, World!\n");return(0);}
or
#include <stdio.h>
int main()
{
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
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.
breaking the overall flow of code that the program achieves.
Line Breaks and Indentation
The addition of white space inside your code is arguably the most important part of good code
structure. Effective use of it can create a visual gauge of how your code flows, which can be very important when returning to your code when you want to maintain it.
Line Breaks
Line breaks should be used in three main parts of your code
•
After precompiler declarations.
•
After new variables are declared.
• Between new paths of code. (i.e. Before the declaration of the function or loop, and after the
closing '}' bracket).
closing '}' bracket).
The following lines of code have line breaks between functions, but not any indention. Note that we have added line numbers to the start of the lines. Using these in actual code will make your
compiler fail, they are only there for reference in this book.
compiler fail, they are only there for reference in this book.
10 #include <stdio.h>
20 int main()
30 {
40 int i=0;
50 printf("Hello, World!");
60 for (i=0;i<1;i++){
70 printf("\n");
80 break;
90 }
100
return(0);
110 }
120
Based on the rules we established earlier, there should now be four line breaks added.
• Between lines 10 and 20, as line 10 is a precompiler declaration
• Between lines 40 and 50, as the block above it contains variable declarations
• Between lines 50 and 60, as it is the beginning of a new path (the 'for' loop)
• Between lines 90 and 100, as it is the end of a path of code
This will make the code much more readable than it was before:
10 #include <stdio.h>
11
20 int main()
30 {
40 int i=0;
41
50 printf("Hello, World!");
51
60 for (i=0;i<1;i++){
70 printf("\n");
80 break;
90 }
91
100
return(0);
110 }
120
But this still isn't as readable as it can be.
Indentation
Although adding simple line breaks between key blocks of code can make code marginally easier to
read, it provides no gauge of the flow of the program. The use of your tab key can be very useful
now: indentation visually separates paths of code by moving their starting points to a new column in
the line. This simple practice will make it much easier to read code. Indentation follows a fairly
simple rule:
read, it provides no gauge of the flow of the program. The use of your tab key can be very useful
now: indentation visually separates paths of code by moving their starting points to a new column in
the line. This simple practice will make it much easier to read code. Indentation follows a fairly
simple rule:
• All code inside a new path (i.e. Between the two '{' brackets '}') should be indented by one
tab more than the code in the previous path.
tab more than the code in the previous path.
So, based on our code from the previous section, there are two paths that require indentation:
•
Lines 40 to 100
•
Lines 70 and 80
10 #include <stdio.h>
11
11
20 int main()
30 {
30 {
40 int i=0;
41
50 printf("Hello, World!");
51
60 for (i=0;i<1;i++){
70 printf("\n");
80 break;
90 }
91
100 return(0);
110 }
120
120
It is now fairly obvious as to which parts of the program fit inside which paths of code. You can tell which parts of the program will loop, and which ones will 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.
immediately noticeable, once many nested loops and paths get added to the structure of the
program, the use of indentation can be very important.
NOTE: Many text editors automatically indent appropriately when you hit the enter/return key.
Comments
Comments in code can be useful for a variety of purposes. They provide the easiest way to point out specific parts of code (and their purpose); as well as providing a visual "split" between various parts of your code. Having a good commentary throughout your code will make it much easier to
remember what specific parts of your code do.
remember what specific parts of your code do.
Comments in modern flavours of C (and many other languages) can come in two forms:
//Single Line Comments
and
/*MultiLine
Comments*/
Comments*/
Note that Single line comments are only a very recent addition to C, and that some
This section is going to focus on the various uses of each form of commentary.
Singleline Comments
Singleline 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 40, to explain what 'int i' is going to do
•
Line 80, to explain why there is a 'break' keyword.
This will make our program look something like
10 #include <stdio.h>
11
11
20 int main()
30 {
40 int i=0;
41
41
//Temporary variable used for 'for' loop.
50 printf("Hello, World!");
51
60 for (i=0;i<1;i++){
70 printf("\n");
80 break; //Exits 'for' loop.
90 }
91
100 return(0);
110 }
Multiline Comments
Multiline 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 path of code. This can be useful in two facets: They make your functions easier to understand, and they make it easier to spot errors in code (if you know what a path is supposed to do, then it is much easier to find the piece of code that is responsible).
As an example, suppose we had a program that was designed to print "Hello, World! " a certain
number of times, on a certain number of lines. 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 multiline 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 multiline comment as the first thing inside a function, to explain the name of the function; the input that it will take, how it takes that input; the output; and the overall procedure that the function is designed to perform. Always leave the technical details to the individual code paths 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 ataglance 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 aestheticallypleasing source code, the multiline comment system allows for the easy addition of starry borders to your comment. These make the comments stand out much more than they would without the border (especially buried deep in source code). They should take a format similar to:
/***************************************
* This is a multi line comment *
* That is surrounded by a *
* Cool, starry border! *
***************************************/
Applied to our original program, we can now include a much more descriptive and readable source
code:
10 #include <stdio.h>
11
20 int main()
30 {
31
/*******************************************************************************
*****
*****
32 * Function: int main()
*
33 * Input : none
*
34 * Output : Returns 0 on success
*
35 * Procedure: Prints "Hello, World!" and a new line to standard output then
exits. *
36
********************************************************************************
****/
****/
40 int i=0; //Temporary variable used for 'for' loop.
41
50 printf("Hello, World!");
51
52 /* FOR LOOP (int i)
53 Prints a new line to standard output, and exits */
60 for (i=0;i<1;i++){
70 printf("\n");
80 break; //Exits 'for' loop.
90 }
91
100 return(0);
110 }
This will allow any outside users of the program an easy way to understand what the code does, and how it works. It also prevents confusion with other likenamed functions.
0 comments:
Post a Comment