recursion and function implementation cs-2301 d-term 20091 recursion and implementation of functions...

65
Recursion and Fun ction Implementat ion CS-2301 D-term 200 9 1 Recursion and Implementation of Functions CS-2301 System Programming C-term 2009 (Slides include materials from The C Programming Language, 2 nd edition, by Kernighan and Ritchie and from C: How to Program, 5 th and 6 th editions, by Deitel and Deitel)

Post on 22-Dec-2015

223 views

Category:

Documents


1 download

TRANSCRIPT

Recursion and Function Implementation

CS-2301 D-term 2009 1

Recursion and Implementation of Functions

CS-2301 System Programming C-term 2009

(Slides include materials from The C Programming Language, 2nd edition, by Kernighan and Ritchie and from C: How to Program, 5th and 6th editions, by Deitel and Deitel)

Recursion and Function Implementation

CS-2301 D-term 2009 2

Definition

• Recursive Function:– a function that calls itself

• Directly or indirectly

• Each recursive call is made with a new, independent set of arguments

• Previous calls are suspended

• Allows very simple programs for very complex problems

Recursion and Function Implementation

CS-2301 D-term 2009 3

Simplest Example

int factorial(int x) {

if (x <= 1)

return 1;

else

return x * factorial (x-1);

} // factorial

Recursion and Function Implementation

CS-2301 D-term 2009 4

Simplest Example (continued)

int factorial(int x) {

if (x <= 1)

return 1;

else

return x * factorial (x-1);

} // factorial • This puts the current execution of factorial “on hold” and starts a new one

• With a new argument!

Recursion and Function Implementation

CS-2301 D-term 2009 5

Simplest Example (continued)

int factorial(int x) {

if (x <= 1)

return 1;

else

return x * factorial (x-1);

} // factorial • When factorial(x-1) returns, its result it multiplied by x

• Mathematically:– x! = x (x-1)!

Recursion and Function Implementation

CS-2301 D-term 2009 6

Recursion (continued)

• There is an obvious circularity here– factorial calls factorial calls factorial,

etc.

• But each one is called with a smaller value for argument!– Eventually, argument becomes ≤ 1– Invokes if clause to terminate recursion

Recursion and Function Implementation

CS-2301 D-term 2009 7

Simplest Example

int factorial(int x) {

if (x <= 1)

return 1;

else

return x * factorial (x-1);

} // factorial

This if statement “breaks” the recursion

Recursion and Function Implementation

CS-2301 D-term 2009 8

Questions?

Recursion and Function Implementation

CS-2301 D-term 2009 9

More Interesting ExampleTowers of Hanoi

• Move stack of disks from one peg to another• Move one disk at a time• Larger disk may never be on top of smaller disk

Recursion and Function Implementation

CS-2301 D-term 2009 10

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0) { move (disks-1, a, c, b); printf ("Move one disk

from %d to %d\n", a, c); move (disks-1, b, a, c); } // if (disks > 0

return;} // move

Recursion and Function Implementation

CS-2301 D-term 2009 11

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk

from %d to %d\n", a, c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

The function main – gets

number of disks and

invokes function move

Recursion and Function Implementation

CS-2301 D-term 2009 12

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

The function move – where the action is

Recursion and Function Implementation

CS-2301 D-term 2009 13

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

First move all but one of the disks to temporary peg

Recursion and Function Implementation

CS-2301 D-term 2009 14

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

Next, move the remaining disk to the destination peg

Recursion and Function Implementation

CS-2301 D-term 2009 15

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

Finally, move disks from temporary to destination peg

Recursion and Function Implementation

CS-2301 D-term 2009 16

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

Notice that move calls itself twice, but with one fewer disks each time

Recursion and Function Implementation

CS-2301 D-term 2009 17

Why Recursion?

• Not often used by programmers with ordinary skills in some areas, but …

• … some problems are too hard to solve without recursion– Most notably, the compiler!– Tower of Hanoi problem– Most problems involving linked lists and trees

• (Later in the course)

Recursion and Function Implementation

CS-2301 D-term 2009 18

Recursion vs. Iteration

• Some simple recursive problems can be “unwound” into loops

• But code becomes less compact, harder to follow!

• Hard problems cannot easily be expressed in non-recursive code

• Tower of Hanoi

• Robots or avatars that “learn”

• Advanced games

Recursion and Function Implementation

CS-2301 D-term 2009 19

Recursion is so important …

• … that all modern computer architectures specifically support it

• Stack register

• Instructions for manipulating The Stack

• … most modern programming languages allow it

• But not Fortran and not Cobol

Recursion and Function Implementation

CS-2301 D-term 2009 20

Personal Observation

• From my own experience, programming languages and environments that do not support recursion …

• … are usually not rich enough to support a diverse portfolio of programs

• I.e., a wide variety of applications in many different disciplines

Recursion and Function Implementation

CS-2301 D-term 2009 21

Questions?

Recursion and Function Implementation

CS-2301 D-term 2009 22

Data Storage in Memory

• Variables may be automatic or static

• Automatic variables may only be declared within functions and compound statements (blocks)

• Storage allocated when function or block is entered

• Storage is released when function returns or block exits

• Parameters and result are (somewhat) like automatic variables

• Storage is allocated and initialized by caller of function

• Storage is released after function returns to caller.

Recursion and Function Implementation

CS-2301 D-term 2009 23

• Static variables may be declared within or outside of functions

• Storage allocated when program is initialized• Storage is released when program exits

• Static variables outside of functions may be visible to linker

• Compiler sets aside storage for all static variables at compiler or link time

• Values retained across function calls

• Initialization must evaluate to compile-time constant

Static Data

Recursion and Function Implementation

CS-2301 D-term 2009 24

Static Variable Examples

int j; //static, visible to linker & all functs

static float f; // not visible to linker, visible to // to all functions in this program

int fcn (float a, int b) {// nothing inside of {} is visible to linkerint i = b; //automaticdouble g; //automaticstatic double h; //static, not visible to

// linker; value retained from call to call

body – may access j, f, a, b, i, g, h

} // int fcn( … )

Recursion and Function Implementation

CS-2301 D-term 2009 25

Static Variable Examples (continued)

int j; //static, visible to linker & all functs

static float f; // not visible to linker, visible to // to all functions in this program

int fcn (float a, int b) {// nothing inside of {} is visible to linkerint i = b; //automaticdouble g; //automaticstatic double h; //static, not visible to

// linker; value retained from call to call

body – may access j, f, a, b, i, g, h

} // int fcn( … )

Declaration outside any

function:– always static

static storage class:– not

visible to linker

Recursion and Function Implementation

CS-2301 D-term 2009 26

Static Variable Examples (continued)

int j; //static, visible to linker & all functs

static float f; // not visible to linker, visible to // to all functions in this program

int fcn (float a, int b) {// nothing inside of {} is visible to linkerint i = b; //automaticdouble g; //automaticstatic double h; //static, not visible to

// linker; value retained from call to call

body – may access j, f, a, b, i, g, h

} // int fcn( … )

Inside f

unction:– defa

ult is

automati

c

static

storag

e clas

s:– not

visible

to linker

Recursion and Function Implementation

CS-2301 D-term 2009 27

Static Variable Examples (continued)

int j; //static, visible to linker & all functs

static float f; // not visible to linker, visible to // to all functions in this program

int fcn (float a, int b) {// nothing inside of {} is visible to linkerint i = b; //automaticdouble g; //automaticstatic double h; //static, not visible to

// linker; value retained from call to call

body – may access j, f, a, b, i, g, h

} // int fcn( … )

Note: value of h is retained

from one call to next

Value of h is also retained

across recursions

Recursion and Function Implementation

CS-2301 D-term 2009 28

Extern Variables

int j; //static, visible to linker & all functsstatic float f; // not visible to linker, visible to

// to all functions in this programextern float p; // static, defined in another program

int fcn (float a, int b) {// nothing inside of {} is visible to linkerint i = b; //automaticdouble g; //automaticstatic double h; //static, not visible to

// linker; value retained from call to call

body – may access j, f, a, b, i, g, h , p

} // int fcn( … )

extern storage class:– a

static variable defined in

another C program

Recursion and Function Implementation

CS-2301 D-term 2009 29

Questions?

Recursion and Function Implementation

CS-2301 D-term 2009 30

Automatic Variables, Arguments, & Results

• Allocated on The Stack

• Definition – The Stack– A last-in, first-out data structure provided by the

operating system for each running program– For temporary storage of automatic variables,

arguments, function results, and other stuff

• Used by all modern programming languages– Even assembly languages for modern processors– … but not Fortran or Cobol!

Recursion and Function Implementation

CS-2301 D-term 2009 31

Automatic Variables

• Allocated when function or compound statement is entered

• Released when function or compound statement is exited

• Values not retained from execution to next

Recursion and Function Implementation

CS-2301 D-term 2009 32

Arguments and Results

• Arguments are values calculated by caller of function

• Placed on The Stack by caller for use by function

• Function may assign new value to argument, but …

• …caller never looks at argument values again!

• Result is storage allocated by caller• On The Stack

• Assigned by return statement of function

• For use by caller

• Arguments & result are removed by caller• After function returns, after caller has absorbed return value

Recursion and Function Implementation

CS-2301 D-term 2009 33

Typical Implementation of The Stack

• Linear region of memory

• Stack Pointer “growing” downward

• Each time some information is pushed onto The Stack, pointer moves downward

• Each time info is popped off of The Stack, pointer moves back upward

Recursion and Function Implementation

CS-2301 D-term 2009 34

Typical Memory for Running Program (Windows & Linux)

0x00000000

0xFFFFFFFF

address space

program code(text)

static data

heap(dynamically allocated)

stack(dynamically allocated)

PC

SP

Recursion and Function Implementation

CS-2301 D-term 2009 35

Typical Memory for Running Program (Windows & Linux)

0x00000000

0xFFFFFFFF

address space

program code(text)

static data

heap(dynamically allocated)

stack(dynamically allocated)

PC

SP

Heap to be discussed later

in course

Recursion and Function Implementation

CS-2301 D-term 2009 36

How it works

• Imagine the following program:–int factorial(int n){

/* body of factorial function */

} // factorial

• Imagine also the caller:–int x = factorial(100);

• What does compiled code look like?

Recursion and Function Implementation

CS-2301 D-term 2009 37

Compiled code: the caller

int x = factorial(100);

• Put the value “100” somewhere that factorial function can find

• Put the current program counter somewhere so that factorial function can return to the right place in calling function

• Provide a place to put the result, so that calling function can find it

Recursion and Function Implementation

CS-2301 D-term 2009 38

Compiled code: factorial function

• Save the caller’s registers somewhere• Get the argument n from the agreed-upon place• Set aside some memory for local variables and

intermediate results

• Do whatever factorial was programmed to do

• Put the result where the caller can find it• Restore the caller’s registers• Transfer back to the program counter saved by the

caller

Recursion and Function Implementation

CS-2301 D-term 2009 39

Question: Where is “somewhere”?

• So that caller can provide as many arguments as needed (within reason)?

• So that called routine can decide at run-time how much temporary space is needed?

• So that called routine can call any other routine, potentially recursively?

Recursion and Function Implementation

CS-2301 D-term 2009 40

Answer: The Stack

• Calling function• Push space for result, and arguments onto stack

• Push return address and Jump to called function

• Called function• Push registers and automatic storage space onto stack

• Do work of the routine, store result in space pushed above

• Pop registers and automatic storage off stack

• Jump to return address left by calling routine

Recursion and Function Implementation

CS-2301 D-term 2009 41

Typical Address Space (Windows & Linux)

0x00000000

0xFFFFFFFF

Memory address space

program code(text)

static data

heap(dynamically allocated)

stack(dynamically allocated)

PC

SP

Recursion and Function Implementation

CS-2301 D-term 2009 42

Note

• Through the magic of operating systems, each running program has its own memory– Complete with stack & everything else

• Called a process

Windows, Linux, Unix, etc.

Recursion and Function Implementation

CS-2301 D-term 2009 43

Note (continued)

• Not necessarily true in small, embedded systems

• Real-time & control systems

• Mobile phone & PDA

• Remote sensors, instrumentation, etc.

• Multiple running programs share a memory• Each in own partition with own stack

• Barriers to prevent each from corrupting others

Recursion and Function Implementation

CS-2301 D-term 2009 44

Shared Physical Memory

OS Kernel

stack

Process 1

stack

Process 2

0x00000000

0x0000FFFF

Physical

memory

stack

Process 3

Recursion and Function Implementation

CS-2301 D-term 2009 45

Questions?

Recursion and Function Implementation

CS-2301 D-term 2009 46

Why a Stack?

• Engineering reason – Computer architectures without stacks are not “rich” enough to support demands of modern computing

• Multiple running programs at the same time• Complex interactions among running programs• Modern computer languages

• Mathematical reason – To support recursive programs

• Not often used by programmers with ordinary skills , but …• Some problems are too hard to solve without recursion• Most notably, the compiler!

Recursion and Function Implementation

CS-2301 D-term 2009 47

Why a Stack?

• Engineering reason – Computer architectures without stacks are not “rich” enough to support demands of modern computing

• Multiple running programs at the same time• Complex interactions among running programs• Modern computer languages

• Mathematical reason – To support recursive programs

• Not often used by programmers with ordinary skills, but …• Some problems are too hard to solve without it• Also, advanced games and robotics with “intelligent” objects

Recursion and Function Implementation

CS-2301 D-term 2009 48

Tower of Hanoi Program & Use of Stack

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

Recursion and Function Implementation

CS-2301 D-term 2009 49

Implementation on The Stack

nSP

Stack entry for main…

Recursion and Function Implementation

CS-2301 D-term 2009 50

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

Recursion and Function Implementation

CS-2301 D-term 2009 51

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

return address

a = 1c = 2b = 3

disks = n-1

Args for 2nd call to move

Recursion and Function Implementation

CS-2301 D-term 2009 52

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

return address

a = 1c = 2b = 3

disks = n-1

Args for 2nd call to move

Args for subsequent calls to move go here

Recursion and Function Implementation

CS-2301 D-term 2009 53

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

return address

a = 1c = 2b = 3

disks = n-1

Args for 2nd call to move

Eventually, disks = 0, so no more calls to moveAll existing calls return

Recursion and Function Implementation

CS-2301 D-term 2009 54

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

Leaving stack like this again

Recursion and Function Implementation

CS-2301 D-term 2009 55

Tower of Hanoi Program

#include <stdio.h>

void move (int disks, int a, int c, int b);

int main() { int n; printf ("How many disks?"); scanf ("%d", &n); printf ("\n");

move (n, 1, 3, 2);

return 0;} // main

/* PRE: n >= 0; a, b, and c represent some order of the distinct integers 1, 2, 3

POST: the function displays the individual moves necessary to move n disks from needle a to needle c, using needle b as a temporary storage needle

*/

void move (int disks, int a, int c, int b) {

if (disks > 0){ move (disks-1, a, c, b); printf ("Move one disk "

"from %d to %d\n",a,c);

move (disks-1, b, a, c);} // if (disks > 0

return;} // move

Recursion and Function Implementation

CS-2301 D-term 2009 56

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

move now moves one disk from peg1 to peg3, and then calls move again!

Recursion and Function Implementation

CS-2301 D-term 2009 57

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

return address

a = 3c = 2b = 1

disks = n-1

Args for call to move disks back from peg3 to peg2

Recursion and Function Implementation

CS-2301 D-term 2009 58

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

return address

a = 3c = 2b = 1

disks = n-1

Args for call to move back

Args for subsequent calls to move back go here

Recursion and Function Implementation

CS-2301 D-term 2009 59

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

return address

a = 3c = 2b = 1

disks = n-1

Args for 2nd call to move

Eventually, disks = 0, so no more calls to moveAll existing calls return

Recursion and Function Implementation

CS-2301 D-term 2009 60

Implementation on The Stack (continued)

n

SP

Stack entry for main…

return address

a = 1c = 3b = 2

disks = n

Args for call to move

Leaving stack like this again, but with all disks moved to peg 3

Recursion and Function Implementation

CS-2301 D-term 2009 61

Implementation on The Stack

nSP

Stack entry for main…

move returns back to main

Recursion and Function Implementation

CS-2301 D-term 2009 62

Fundamental Principle

• Stack provides a simple mechanism for implementing recursive functions

• Arbitrary numbers of intermediate functions

• Eventually, something must break the circularity of recursion

• Or stack will grow until it overflows memory!

Recursion and Function Implementation

CS-2301 D-term 2009 63

Note on Recursive Functions

• Some simple recursive functions can be “unwound” into loops – e.g.,

int factorial(int n) {return (n <= 1) ? 1 : (n * factorial(n-1));

} //factorial

is equivalent toint factorial(int n) {int product = 1;

for (int k=1; k <= n; k++)

product *= k;return product

} //factorial

Recursion and Function Implementation

CS-2301 D-term 2009 64

Note on Recursive Functions (continued)

• Other recursive functions are much too difficult to understand if unwound

• E.g., Tower of Hanoi• Keeping track of which disk is on which peg

requires superhuman intellect, very complex code!

Recursion and Function Implementation

CS-2301 D-term 2009 65

Questions?