Tuesday, July 16, 2013

Macros versus Functions

In the above example a macro was used to calculate the area of the circle. As we know, even a function can be written to calculate the area of the circle. Though macro calls are ‘like’ function calls, they are not really the same things. Then what is the difference between the two?
In a macro call the preprocessor replaces the macro template with its macro expansion, in a stupid, unthinking, literal way. As against this, in a function call the control is passed to a function along with certain arguments, some calculations are performed in the function and a useful value is returned back from the function.
This brings us to a question: when is it best to use macros with arguments and when is it better to use a function? Usually macros make the program run faster but increase the program size, whereas functions make the program smaller and compact.
If we use a macro hundred times in a program, the macro expansion goes into our source code at hundred different places, thus increasing the program size. On the other hand, if a function is used, then even if it is called from hundred different places in
the program, it would take the same amount of space in the program.
But passing arguments to a function and getting back the returned value does take time and would therefore slow down the program. This gets avoided with macros since they have already been expanded and placed in the source code before compilation.
Moral of the story is—if the macro is simple and sweet like in our examples, it makes nice shorthand and avoids the overheads associated with function calls. On the other hand, if we have a fairly large macro and it is used fairly often, perhaps we ought to replace it with a function.


File Inclusion

The second preprocessor directive we’ll explore in this chapter is file inclusion. This directive causes one file to be included in another. The preprocessor command for file inclusion looks like this:
#include "filename"
and it simply causes the entire contents of filename to be inserted into the source code at that point in the program. Of course this presumes that the file being included is existing. When and why this feature is used? It can be used in two cases:
(a) If we have a very large program, the code is best divided into several different files, each containing a set of related functions. It is a good programming practice to keep different sections of a large program separate. These files are #included at the beginning of main program file.
(b) There are some functions and some macro definitions that we need almost in all programs that we write. These commonly needed functions and macro definitions can be stored in a file, and that file can be included in every program we write, which would add all the statements in this file to our program as if we have typed them in.
It is common for the files that are to be included to have a .h extension. This extension stands for ‘header file’, possibly because it contains statements which when included go to the head of your program. The prototypes of all the library functions are grouped into different categories and then stored in different header files. For example prototypes of all mathematics related functions are stored in the header file ‘math.h’, prototypes of console input/output functions are stored in the header file ‘conio.h’, and so on.
Actually there exist two ways to write #include statement. These are:
#include "filename"
#include <filename>
The meaning of each of these forms is given below:
#include "goto.c"
This command would look for the file goto.c in the current directory as well as the specified list of directories as mentioned in the include search path that might have been set up.
#include <goto.c>
This command would look for the file goto.c in the specified list of directories only.
The include search path is nothing but a list of directories that would be searched for the file being included. Different C compilers let you set the search path in different manners. If you are using Turbo C/C++ compiler then the search path can be set up by selecting ‘Directories’ from the ‘Options’ menu. On doing this a dialog box appears. In this dialog box against ‘Include Directories’ we can specify the search path. We can also specify multiple include paths separated by ‘;’ (semicolon) as shown below:
c:\tc\lib ; c:\mylib ; d:\libfiles
The path can contain maximum of 127 characters. Both relative and absolute paths are valid. For example ‘..\dir\incfiles’ is a valid path.

Macros with arguments

The macros that we have used so far are called simple macros. Macros can have arguments, just as functions can. Here is an example that illustrates this fact.
#define AREA(x) ( 3.14 * x * x )
main( )
{
float r1 = 6.25, r2 = 2.5, a ;
a = AREA ( r1 ) ;
printf ( "\nArea of circle = %f", a ) ;
a = AREA ( r2 ) ;
printf ( "\nArea of circle = %f", a ) ;
}
Here’s the output of the program...
Area of circle = 122.656250
Area of circle = 19.625000

In this program wherever the preprocessor finds the phrase AREA(x) it expands it into the statement ( 3.14 * x * x ). However, that’s not all that it does. The x in the macro template AREA(x) is an argument that matches the x in the macro expansion ( 3.14 * x * x ). The statement AREA(r1) in the program causes the variable r1 to be substituted for x. Thus the statement AREA(r1) is equivalent to:
( 3.14 * r1 * r1 )
After the above source code has passed through the preprocessor, what the compiler gets to work on will be this:
main( )
{
float r1 = 6.25, r2 = 2.5, a ;
a = 3.14 * r1 *r1 ;
printf ( "Area of circle = %f\n", a ) ;
a = 3.14 *r2 * r2 ;
printf ( "Area of circle = %f", a ) ;
}
Here is another example of macros with arguments:
#define ISDIGIT(y) ( y >= 48 && y <= 57 )
main( )
{
char ch ;
printf ( "Enter any digit " ) ;
scanf ( "%c", &ch ) ;
if ( ISDIGIT ( ch ) )
printf ( "\nYou entered a digit" ) ;
else
printf ("\nIllegal input" ) ;
}
Here are some important points to remember while writing macros with arguments:
(a)
(b)
Be careful not to leave a blank between the macro template and its argument while defining the macro. For example, there should be no blank between AREA and (x) in the definition, #define AREA(x) ( 3.14 * x * x )
If we were to write AREA (x) instead of AREA(x), the (x) would become a part of macro expansion, which we certainly don’t want. What would happen is, the template would be expanded to
( r1 ) ( 3.14 * r1 * r1 )
which won’t run. Not at all what we wanted.
The entire macro expansion should be enclosed within parentheses. Here is an example of what would happen if we fail to enclose the macro expansion within parentheses.
#define SQUARE(n) n * n
main( )
{
int j ;
j = 64 / SQUARE ( 4 ) ;
printf ( "j = %d", j ) ;
}
The output of the above program would be:
j = 64
whereas, what we expected was j = 4.
What went wrong? The macro was expanded into
j = 64 / 4 * 4 ;
which yielded 64.

C pre-processor

There are several steps involved from the stage of writing a C program to the stage of getting it executed. Figure 7.1 shows these different steps along with the files created during each stage. You can observe from the figure that our program passes through several processors before it is ready to be executed. The input and output to each of these processors is shown in Figure 7.2.
Note that if the source code is stored in a file PR1.C then the expanded source code gets stored in a file PR1.I. When this expanded source code is compiled the object code gets stored in PR1.OBJ. When this object code is linked with the object code of library functions the resultant executable code gets stored in PR1.EXE.
The preprocessor offers several features called preprocessor directives. Each of these preprocessor directives begin with a # symbol. The directives can be placed anywhere in a program but are most often placed at the beginning of a program, before the first function definition. We would learn the following preprocessor directives begin with a # symbol. The directives can be placed anywhere in a program but are most often placed at the beginning of a program, before the first function definition. We would learn the following preprocessor directives here:
(a) Macro expansion
(b) File inclusion
(c) Conditional Compilation
(d) Miscellaneous directives

Macro Expansion
Have a look at the following program.
#define UPPER 25
main( )
{
int i ;
for ( i = 1 ; i <= UPPER ; i++ )
printf ( "\n%d", i ) ;
}
In this program instead of writing 25 in the for loop we are writing it in the form of UPPER, which has already been defined before main( ) through the statement,
#define UPPER 25
This statement is called ‘macro definition’ or more commonly, just a ‘macro’. What purpose does it serve? During preprocessing, the preprocessor replaces every occurrence of UPPER in the program with 25. Here is another example of macro definition
#define PI 3.1415
main( )
{
float r = 6.25 ;
float area ;
area = PI * r * r ;
printf ( "\nArea of circle = %f", area ) ;
}

UPPER and PI in the above programs are often called ‘macro templates’, whereas, 25 and 3.1415 are called their corresponding ‘macro expansions’.
When we compile the program, before the source code passes to the compiler it is examined by the C preprocessor for any macro definitions. When it sees the #define directive, it goes through the entire program in search of the macro templates; wherever it finds one, it replaces the macro template with the appropriate macro expansion. Only after this procedure has been completed is the program handed over to the compiler.
In C programming it is customary to use capital letters for macro template. This makes it easy for programmers to pick out all the macro templates when reading through the program.

Scope rule of functions

Look at the following program
main( )
{
int i = 20 ;
display ( i ) ;
}
display ( int j )
{
int k = 35 ;
printf ( "\n%d", j ) ;
printf ( "\n%d", k ) ;
}
In this program is it necessary to pass the value of the variable i to the function display( )? Will it not become automatically available.
to the function display( )? No. Because by default the scope of a variable is local to the function in which it is defined. The presence
of i is known only to the function main( ) and not to any other function. Similarly, the variable k is local to the function display( ) and hence it is not available to main( ). That is why to make the value of i available to display( ) we have to explicitly pass it to display( ). Likewise, if we want k to be available to main( ) we will have to return it to main( ) using the return statement. In general we can say that the scope of a variable is local to the function in which it is defined.


Calling Convention

Calling convention indicates the order in which arguments are passed to a function when a function call is encountered. There are two possibilities here:
(a)
(b)
Arguments might be passed from left to right.
Arguments might be passed from right to left.
C language follows the second order.
Consider the following function call:
fun (a, b, c, d ) ;
In this call it doesn’t matter whether the arguments are passed from left to right or from right to left. However, in some function call the order of passing arguments becomes an important consideration. For example:
int a = 1 ;
printf ( "%d %d %d", a, ++a, a++ ) ;
It appears that this printf( ) would output 1 2 3.
This however is not the case. Surprisingly, it outputs 3 3 1. This is because C’s calling convention is from right to left. That is, firstly

1 is passed through the expression a++ and then a is incremented to 2. Then result of ++a is passed. That is, a is incremented to 3 and then passed. Finally, latest value of a, i.e. 3, is passed. Thus in right to left order 1, 3, 3 get passed. Once printf( ) collects them it prints them in the order in which we have asked it to get them printed (and not the order in which they were passed). Thus 3 3 1 is printed.

Monday, July 15, 2013

Functions and Pointers 2

As we have noted earlier the program execution always begins with main( ). Except for this fact all C functions enjoy a state of perfect equality. No precedence, no priorities, nobody is nobody’s boss. One function can call another function it has already called but has in the meantime left temporarily in order to call a third function which will sometime later call the function that has called it, if you understand what I mean. No? Well, let’s illustrate with an example.
main( )
{
printf ( "\nI am in main" ) ;
italy( ) ;
printf ( "\nI am finally back in main" ) ;
}
italy( )
{
printf ( "\nI am in italy" ) ;
brazil( ) ;
printf ( "\nI am back in italy" ) ;
}
brazil( )
{
printf ( "\nI am in brazil" ) ;
argentina( ) ;
}
argentina( )
{
printf ( "\nI am in argentina" ) ;
}
And the output would look like...
I am in main
I am in italy
I am in brazil
I am in argentina
I am back in italy
I am finally back in main
Here, main( ) calls other functions, which in turn call still other functions. Trace carefully the way control passes from one function to another. Since the compiler always begins the program execution with main( ), every function in a program must be called directly or indirectly by main( ). In other words, the main( ) function drives other functions.
Let us now summarize what we have learnt so far.
(a)
(b)
(c)
C program is a collection of one or more functions.
A function gets called when the function name is followed by a semicolon. For example,
main( )
{
argentina( ) ;
}
A function is defined when function name is followed by a pair of braces in which one or more statements may be
present. For example,
argentina( )
{
statement 1 ;
statement 2 ;
statement 3 ;
}
(d)
(e)
(f)
Any function can be called from any other function. Even main( ) can be called from other functions. For example,
main( )
{
message( ) ;
}
message( )
{
printf ( "\nCan't imagine life without C" ) ;
main( ) ;
}
A function can be called any number of times. For example,
main( )
{
message( );
message( ) ;
}
message( )
{
printf ( "\nJewel Thief!!" ) ;
}
The order in which the functions are defined in a program and the order in which they get called need not necessarily be same. For example,
main( )
{
message1( );
message2( ) ;
}
message2( )
{
printf ( "\nBut the butter was bitter" ) ;
message1( )
{
printf ( "\nMary bought some butter" ) ;
}
Here, even though message1( ) is getting called before message2( ), still, message1( ) has been defined after message2( ). However, it is advisable to define the functions in the same order in which they are called. This makes the program easier to understand.
(g)
(h)
(i)
A function can call itself. Such a process is called ‘recursion’. We would discuss this aspect of C functions later in this chapter.
A function can be called from other function, but a function cannot be defined in another function. Thus, the following program code would be wrong, since argentina( ) is being defined inside another function, main( ).

Functions and Pointers

A function is a self-contained block of statements that perform a coherent task of some kind. Every C program can be thought of as a collection of these functions. As we noted earlier, using a function is something like hiring a person to do a specific job for you. Sometimes the interaction with this person is very simple; sometimes it’s complex.
Suppose you have a task that is always performed exactly in the same way—say a bimonthly servicing of your motorbike. When you want it to be done, you go to the service station and say, “It’s time, do it now”. You don’t need to give instructions, because the mechanic knows his job. You don’t need to be told when the job is done. You assume the bike would be serviced in the usual way, the mechanic does it and that’s that.
Let us now look at a simple C function that operates in much the same way as the mechanic. Actually, we will be looking at two things—a function that calls or activates the function and the function itself.

main( )
{
message( ) ;
printf ( "\nCry, and you stop the monotony!" ) ;
}
message( )
{
printf ( "\nSmile, and the world smiles with you..." ) ;
}
And here’s the output...
Smile, and the world smiles with you...
Cry, and you stop the monotony!
Here, main( ) itself is a function and through it we are calling the function message( ). What do we mean when we say that main( ) ‘calls’ the function message( )? We mean that the control passes to the function message( ). The activity of main( ) is temporarily
suspended; it falls asleep while the message( ) function wakes up and goes to work. When the message( ) function runs out of statements to execute, the control returns to main( ), which comes to life again and begins executing its code at the exact point where it left off. Thus, main( ) becomes the ‘calling’ function, whereas message( ) becomes the ‘called’ function

If you have grasped the concept of ‘calling’ a function you are prepared for a call to more than one function. Consider the following example:
main( )
{
printf ( "\nI am in main" ) ;
italy( ) ;
brazil( ) ;
argentina( ) ;
}
italy( )
{
printf ( "\nI am in italy" ) ;
}
brazil( )
{
printf ( "\nI am in brazil" ) ;
}
argentina( )
{
printf ( "\nI am in argentina" ) ;
}
The output of the above program when executed would be as under:
I am in main
I am in italy
I am in brazil
I am in argentina
From this program a number of conclusions can be drawn:
− Any C program contains at least one function.
− If a program contains only one function, it must be main( ).
− If a C program contains more than one function, then one (and only one) of these functions must be main( ), because program execution always begins with main( ).
− There is no limit on the number of functions that might be present in a C program.
− Each function in a program is called in the sequence specified by the function calls in main( ).

Loops

The versatility of the computer lies in its ability to perform a set of instructions repeatedly. This involves repeating some portion of the program either a specified number of times or until a particular condition is being satisfied. This repetitive o
throug
program. They are: (a) Using a for statement (b) Using a while statement (c) Using a do-while statement
Each of these methods is discussed in the following pages.

The While loop

It is often the case in programming that you want to do something
a fixed number of times. Perhaps you want to calculate gross
salaries of ten different persons, or you want to convert
temperatures from centigrade to fahrenheit for 15 different cities.
The while loop is isimple example, w
deally suited for such cases.
/* Calculation of simple interest for 3 sets of p, n and r */
main( )
{
int p, n, count ; float r, si ;
count = 1 ;
while ( count <= 3 )
{
printf ( "\nEnter values of p, n and r " ) ;
d %f", &p, &n, &r ) ;
n * r / 100 ;
printf ( "Simple interest = Rs. %f", si ) ;
count=count+1;
}}


The general form of while is as shown below:
initialise loop counter ;
increment loop counter ;
o about while...