Thursday, July 3, 2008

Functions (2)




Functions have to be declared, defined and called. You remember #include in all your programs. That stdio.h file contains the declarations of many of your library function. (Note not defintion but just declaration).




Exercise 1: Search for the file stdio.h and see the contents of the file

A function declaration as well as the header of the function must specify the name of the function, parameter list and also return type. If you do not mention the return type, c compiler assumes that the function returns an int.

float findHalf(int n)
{
return (n/2.0);
}
Now define this function after defintion of main(). Now call this function say



printf("%f",findHalf(15));
What do answer do you obtain? 7.5? 7? No. Answer will be zero.



The compiler does not know about the function(it does not see declaration or definition before calling the function) and thinks it is an int function. Wrong format specifier %f for int. Hence the wrong answer.



(Please note that, if the function is defined before main(), then the function definition itself serves the purpose of declaration. )



Now declare the function as
findHalf(int );

You don't see change in the output. Again since you haven't mentioned return type, compiler thinks it is an int function.

float findHalf(int );

This declaration gives you the correct answer.

Ex 2: Write a program to print how many days are left for you on this earth making an assumption that you live upto 80 years. OK, ok, if you think it is too morbid, write a program to print how many days old are you.

Let us write some bit manipulation programs which Ritchie is so fond of. First write a function to find the number of 1 bits in the given int.


int numBits(unsigned int n )

{

int c=0;

while(n)

{

if (n&1)

c++;

n=n>>1;

}

return c;

}



But one of Ritchie's exercises asks you to solve this program without using loop. He has also given hint. Try it.






You may want to know where are the variables within the function stored. All the local variables are stored in the stack. Once a function is called, a new stack frame is created. This stack frame has all local variables, parameters and return address (which statement to execute after returning from the function), temporaries, saved registers, place for return value etc. The function accesses the values from the top most stack frame. Hence a function can not access variables defined in other functions including main()












Now look at this image fro http://www.oaklib.org/ which shows the ways stack frames are organised when 3 functions are being called.


In Linux OS, compile your program with the option -g (enables debugging). Start the gdb and single step through the program and observe the stack frames using bt.




bt can also be used in understanding the recursive functions better. A recursive function is the one which calls itself. Finding the factorial is most taught recursive function.

int factorial(int n)

{

if (n)

return (n*factorial(n-1);

else

return 1;

}

Remember the following rules when writing a recursive function. The function should not call recursion for atleast one value and other values must proceed towords that value. (Here recursion is not called for 0 and n is getting reduced ) If this condition is not met, the function will be infinitely recursive. Here if return (n*factorial(n-1); only this statement is used then the function will never end.

Don't be tempted make the function recursive unnecessarily. Recursive function create many stack frames , one frame for each call and hence eat up memory. This makes the program slow as well. You should try to avoid such situations, especially when you have limited memory e.g. embedded systems.

The parameters sent to the function are copied to the stack and these copies will be manipulated. Original parameters are unaltered.

int doubleNum(int n)

{

n=n<<1;

}

int main()

{

int n = 10; doubleNum(n);printf("%d",n);//will not print 20

}


The function modifies the local copy of n and does not modify n in main. If you really need to change the parameter, then send the address of variable ie a pointer

No comments: