More on FunctionsCS-2301 B-term 2008 1
More on Functions
CS-2301, System Programming for Non-majors
(Slides include materials from The C Programming Language, 2nd ed., by Kernighan and Ritchie and from C: How to Program, 5th ed., by Deitel and Deitel)
More on FunctionsCS-2301 B-term 2008 2
Data Storage in Memory
• Variables may be automatic or static
• Automatic variables may only be declared within functions and compound statements
• Storage allocated when function is entered
• Storage is released when function returns
• Arguments and result are (somewhat) like automatic variables
• Storage is allocated and initialized by caller of function
• Storage is released after function returns to caller.
More on FunctionsCS-2301 B-term 2008 3
• 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
More on FunctionsCS-2301 B-term 2008 4
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( … )
More on FunctionsCS-2301 B-term 2008 5
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
More on FunctionsCS-2301 B-term 2008 6
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
More on FunctionsCS-2301 B-term 2008 7
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
More on FunctionsCS-2301 B-term 2008 8
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
More on FunctionsCS-2301 B-term 2008 10
Automatic VariablesArguments & 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!
More on FunctionsCS-2301 B-term 2008 11
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
More on FunctionsCS-2301 B-term 2008 12
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
More on FunctionsCS-2301 B-term 2008 13
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
More on FunctionsCS-2301 B-term 2008 14
Typical Memory for Running Program (Windows & Linux)
0x00000000
0xFFFFFFFF
address space
program code(text)
static data
heap(dynamically allocated)
stack(dynamically allocated)
PC
SP
More on FunctionsCS-2301 B-term 2008 15
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
More on FunctionsCS-2301 B-term 2008 16
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?
More on FunctionsCS-2301 B-term 2008 17
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
More on FunctionsCS-2301 B-term 2008 18
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
More on FunctionsCS-2301 B-term 2008 19
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?
• We will explain recursion shortly
More on FunctionsCS-2301 B-term 2008 20
Answer: The Stack
• Calling function• Push return address, space for result, and arguments onto stack
• 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
More on FunctionsCS-2301 B-term 2008 21
Typical Address Space (Windows & Linux)
0x00000000
0xFFFFFFFF
Memory address space
program code(text)
static data
heap(dynamically allocated)
stack(dynamically allocated)
PC
SP
More on FunctionsCS-2301 B-term 2008 22
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.
More on FunctionsCS-2301 B-term 2008 23
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
More on FunctionsCS-2301 B-term 2008 24
Shared Physical Memory
OS Kernel
stack
Process 1
stack
Process 2
0x00000000
0x0000FFFF
Physical
memory
stack
Process 3
More on FunctionsCS-2301 B-term 2008 26
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 by ordinary programmers with ordinary skills• Some problems are too hard to solve without it• Most notably, the compiler!
More on FunctionsCS-2301 B-term 2008 27
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 by ordinary programmers with ordinary skills• Some problems are too hard to solve without it• Most notably, the compiler!
More on FunctionsCS-2301 B-term 2008 28
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!
More on FunctionsCS-2301 B-term 2008 29
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
More on FunctionsCS-2301 B-term 2008 30
Definition – Recursion
• When a function calls itself, directly or indirectly
• When a mathematical or programmatic concept is defined in terms of itself
• E.g., definition of compound statement in §A9.3, p.223
More on FunctionsCS-2301 B-term 2008 31
Definition – Recursion
• When a function calls itself, directly or indirectly
• When a mathematical or programmatic concept is defined in terms of itself
• E.g., definition of compound statement in §A9.3, p.223
In both cases, something is needed to break the circularity
More on FunctionsCS-2301 B-term 2008 32
Example – Towers 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
More on FunctionsCS-2301 B-term 2008 33
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, b, c); printf ("Move one disk
from %d to %d\n", a, c); move (disks-1, b, c, a); } // if (disks > 0
return;} // move
More on FunctionsCS-2301 B-term 2008 34
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
The function main – gets
number of disks and
invokes function move
More on FunctionsCS-2301 B-term 2008 35
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
The function move – where the action is
More on FunctionsCS-2301 B-term 2008 36
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
First move all but one of the disks to temporary peg
More on FunctionsCS-2301 B-term 2008 37
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
Next, move the remaining disk to the destination peg
More on FunctionsCS-2301 B-term 2008 38
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
Finally, move disks from temporary to destination peg
More on FunctionsCS-2301 B-term 2008 39
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
Notice that move calls itself twice, but with one fewer disks each time
More on FunctionsCS-2301 B-term 2008 41
Implementation on The Stack (continued)
n
SP
Stack entry for main…
return address
a = 1c = 3b = 2
disks = n
Args for call to move
More on FunctionsCS-2301 B-term 2008 42
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
More on FunctionsCS-2301 B-term 2008 43
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
More on FunctionsCS-2301 B-term 2008 44
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
More on FunctionsCS-2301 B-term 2008 45
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
More on FunctionsCS-2301 B-term 2008 46
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
More on FunctionsCS-2301 B-term 2008 47
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, b, c); printf ("Move one disk
from %d to %d\n", a, c);
move (disks-1, b, c, a);} // if (disks > 0
return;} // move
More on FunctionsCS-2301 B-term 2008 48
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!
More on FunctionsCS-2301 B-term 2008 49
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
More on FunctionsCS-2301 B-term 2008 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
return address
a = 3c = 2b = 1
disks = n-1
Args for call to move back
Args for subsequent calls to move back go here
More on FunctionsCS-2301 B-term 2008 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 = 3c = 2b = 1
disks = n-1
Args for 2nd call to move
Eventually, disks = 0, so no more calls to moveAll existing calls return
More on FunctionsCS-2301 B-term 2008 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
Leaving stack like this again, but with all disks moved to peg 3
More on FunctionsCS-2301 B-term 2008 53
Implementation on The Stack
nSP
Stack entry for main…
move returns back to main
More on FunctionsCS-2301 B-term 2008 54
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!
More on FunctionsCS-2301 B-term 2008 55
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
More on FunctionsCS-2301 B-term 2008 56
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!