Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming Microcontrollers in C, 2-nd edit (Ted Van Sickle, 2001).pdf
Скачиваний:
296
Добавлен:
12.08.2013
Размер:
7.2 Mб
Скачать

Recursion 61

content of the buffer at that location is returned to the calling pro­ gram. In the event that sp is 0 when the pull operation is executed, a stack underflow message is sent to the screen prior to exiting the program.

The advantage to our making the buffer and the stack pointer in the stack functions static can be easily seen. Suppose that these vari­ ables could be accessed from anywhere in the program. In that case, it would not be necessary for the programmer to call the functions push or pull to stack and unstack data. If several different pro­ grammers were using the same stack for different tasks in one large program, it would be possible for different programmers to access the stack as expected, or from their own tasks. Suppose a program­ mer made the mistake of pre-decrementing the stack pointer on stacking and post-incrementing the stack pointer on unstacking. The whole program would suddenly be in chaos. Therefore, masking these variables from the rest of the program can reduce serious potential debugging problems.

Recursion

A recursive routine is one that calls itself. The C language is supposed to produce recursive code. Compilers for large machines usually support recursion, but recursion is often one of the first casu­ alties on small microcontrollers. Automatic variables are created when a function is entered, and they are stored on the stack. Therefore, each time a function is called, a new stack frame is created, and variables in place from an earlier execution of the function are unal­ tered. Such a function is called re-entrant, and re-entrant functions are also recursive. An example of a simple recursive function is the factorial:

n! = n*(n-1)*(n-2)*....

*2*1

An interesting observation that can be made of factorial is that

n! = n*(n-1)!

or n factorial equals n times n-1 factorial. Also, the factorial of 0 is defined as 1. With these definitions, it is possible to write the follow­ ing recursive function to calculate the factorial of a number:

long factorial( int n)

62Chapter 1 Introduction to C

{

if(n==0) return 1;

else

return n*factorial(n-1);

}

This surprisingly simple function calculates the factorial. When­ ever you write a recursive routine, it is important to have means of getting out of the routine. In the above case, when the argument reaches zero, the function returns a result rather than calling itself again. At that time the routine will work itself back a level at a time until it reaches the initial factorial call, and the calculation will be done.

Recursion can create some elegant code in that the code is very simple—often too simple. There is a cost in the use of recursive code, and that is stack space. Each time a function call is made, the argu­ ment is placed on the stack and a subroutine call is executed. As a minimum, the return address is two bytes, and the value of the argu­ ment is also two bytes. Thus, at least four bytes of stack space are needed for each function call. That is no problem when the factorial of a small number is calculated. (The factorial of 13 is larger than can be held in a long, so only small numbers can be considered for a factorial.) However, if a recursive function is written that calls it­ self many times, it is possible to get into stack overflow problems.

Another interesting recursive routine is the function to calculate a Fibonacci number. A Fibonacci number sequence is described by the following function:

long fib(int n)

{

if(n==1) return 1;

else if(n==0) return 1;

else

return fib(n-1) + fib(n-2);

}

This sneaky function calls itself twice. Some interesting characteris­ tics of this function are left to the exercises that follow.

Summary 63

EXERCISES

1.Write a function to calculate the Fibonacci number for 10, 20, 30, and 40.

2.Devise a means for determining the number of times the fib func­ tion is called in the above program. What is this number for fib(20)?

3.A separate problem from the number of times the function is called is the number of times the function is called without exiting through the bottom of the function. This term is called the depth of the function. Determine the maximum depth of the fib() function in calculating fib(20).

4.Repeat problem 1, but rewrite the Fibonacci number function so that it does not employ recursion. How does the time to execute this version of the fib(30) compared to that above?

Summary

The basics of writing programs in C have been discussed in this chapter. Several important concepts have been skipped over in this presentation and will be covered in Chapter 2.

If you have not done so, it is recommended that you enter and compile each example shown. These programs will all compile and run under the MIX PowerC Compiler, the Cosmic compiler for the M68HC11, the M68HC16, and the M68300 series of chips. They also compile on the DIAB MCORE compiler. With the exception of the MIX PowerC compiler, all of the compilers listed are cross com­ pilers that run on a PC platform, but compile code for another computer.

The ANSI version of the language is the current standard, and none of the classical C constructs have been introduced in this text. It is not to the programmer’s advantage to use the classical version of the language, even though programs that conform to classical C will compile on an ANSI compliant compiler. Any version of a C++ com­ piler structured to compile C code will also compile ANSI C code. The DIAB compiler listed above is a C/C++ compiler.