Title: Functions
1Functions
2Outline
- Function Definition
- The return Statement
- Function Prototypes
- Example
- An Alternate Style for Function Definition Order
3Outline (continued)
- Function Invocation and Call-by-Value
- Developing a Large program
- Using Assertions
- Scope Rules
- Storage Classes
- Static External Variables
- Default Initialization
- Recursion
- Example
4Function Definition
- breaking one big code into small, manageable
pieces - top-down method of programming
- at least one function main(), which calls other
functions - definition of function
header
type function_name (parameters) statements
body
5Function Definition
passing value in
int factorial(int n) int i, product 1 for
(i2 ilt2i) product i return product
6Function Definition
passing value in
void wrt_address(void) printf("s\ns\ns\n\n",
" ", I am
here ",
")
7Function Definition
double twice(double x) return
(2.0x) int all_add(int a, int b) int
c return (abc)
8Function Definition
- local and global variables
- variable declared inside the body of a function
is called "local"variable. It is valid only
inside the block. - variable declared outside any bodies is called a
global variable. It is valid for anywhere. - example
9includeltstdio.hgt int a33 int main(void)
int b77 printf("ad\n",a) printf("bd\n",b)
return 0
10The return Statement
- return a value to the calling function
- It implicitly casts type before return
return return a return (ab)
11The return Statement
- multiple return statements
double absolute_value(double x) if (xgt0.0)
return x else return x
12Function Prototypes
- function prototypes register the function and
tells the compiler the number and type of
arguments, and return type
type function_name(parameters)
example double sqrt(double) void f(char c, int
i)
13Example
include ltstdio.hgt define N 7 long
power(int, int) void prn_heading(void) void
prn_tbl_of_powers(int) int main(void)
prn_heading() prn_tbl_of_powers(N) return
0
call two void functions
14void prn_heading(void) printf("\n A
TABLE OF POWERS \n\n") void
prn_tbl_of_powers(int n) int i, j for
(i 1 i lt n i) for (j 1 j lt n
j) if (j 1)
printf("ld", power(i, j)) else
printf("9ld", power(i, j))
putchar('\n')
15 long power(int m, int n) int i long
product 1 for (i 1 i lt n i)
product m return product
16 A TABLE OF POWERS 1 1
1 1 1 1 1 2
4 8 16 32 64 128 3
9 27 81 243 729
2187 4 16 64 256 1024
4096 16384 5 25 125 625
3125 15625 78125 6 36 216
1296 7776 46656 279936 7 49
343 2401 16807 117649 823543
17An Alternate Style for Function Definition Order
- Use function definition to replace function
prototypes - Place function definition in order
18include ltstdio.hgt define N 7 void
prn_heading(void) printf("\n A TABLE
OF POWERS \n\n") long power(int m, int
n) int i long product 1 for
(i 1 i lt n i) product m
return product
19 void prn_tbl_of_powers(int n) int i,
j for (i 1 i lt n i) for (j
1 j lt n j) if (j 1)
printf("ld", power(i, j)) else
printf("9ld", power(i, j))
putchar('\n')
20 int main(void) prn_heading()
prn_tbl_of_powers(N) return 0
21Function Invocation and Call-by-Value
- calling function invokes the called function,
then return back to the normal track. - calling function should provide number of
parameters which match the argument list of
called functions. - Each argument is evaluated before the value is
passed to the corresponding parameter
22include ltstdio.hgt int main(void) int n
3, sum, compute_sum(int) printf("d\n", n)
/ 3 is printed / sum
compute_sum(n) printf("d\n", n) / 3
is printed / printf("d\n", sum) / 6
is printed / return 0
n remains unchanged
23int compute_sum(int n) / sum the integers
from 1 to n / int sum 0 for ( n
gt 0 --n) / stored value of n is changed
/ sum n return sum
3 3 6
24Developing a Large program
- put the following items into the hearder.h file.
- include, define, templates of enumeration,
templates of structure and union types, other
programming constructs, and finally a list of
function prototypes at the bottom. - each c code include the header.h file
- example pgm
25include ltstdio.hgt include ltstdlib.hgt define
N 3 void fct1(int k) void
fct2(void) void wrt_info(char )
pgm.h
26include "pgm.h" int main(void) char
ans int i, n N printf("s",
"This program does not do very much.\n" "Do
you want more information? ") scanf(" c",
ans) if (ans 'y' ans 'Y')
wrt_info("pgm") for (i 0 i lt n i)
fct1(i) printf("Bye!\n") return 0
main.c
27include "pgm.h" void fct1(int n) int
i printf("Hello from fct1()\n") for (i
0 i lt n i) fct2() void
fct2(void) printf("Hello from fct2()\n")
fct.c
28include "pgm.h" void wrt_info(char
pgm_name) printf("Usage s\n\n",
pgm_name) printf("s\n", "This program
illustrates how one can write a program\n"
"in more than one file. In this example, we have
a\n" "single .h file that gets included at
the top of our\n" "three .c files. Thus
the .h file acts as the \"glue\"\n" "that
binds the program together.\n" "\n"
"Note that the functions fct1() and fct2() when
called\n" "only say \"hello.\" When
writing a serious program, the\n"
"programmer sometimes does this in a first
working\n" "version of the code.\n")
wrt.c
29execution command cc -o pgm
main.c fct.c wrt.c or cc o pgm
.c or You can download big C code on internet.
Try ftp//ftp.aw.com Use the following line to
count words, to see whether it s a big program
package or not. wc READ_ME .h .c makefile
30Alternatively, you can create a makefile, and
then type the make command make a.out
CC gcc CFLAGS -Wall EXEC
a.out INCLS LIBS OBJS main.o
fct.o wrt.o (EXEC) (OBJS) _at_echo
"linking ..." _at_(CC) (CFLAGS) -o
(EXEC) (OBJS) (LIBS) (OBJS) pgm.h
(CC) (CFLAGS) (INCLS) -c .c relink
_at_echo "relinking ..." _at_(CC)
(CFLAGS) -o (EXEC) (OBJS) (LIBS)
31This program does not do very much. Do you want
more information? y Usage pgm This program
illustrates how one can write a program in more
than one file. In this example, we have a single
.h file that gets included at the top of
our three .c files. Thus the .h file acts as the
"glue" that binds the program together. Note
that the functions fct1() and fct2() when
called only say "hello." When writing a serious
program, the programmer sometimes does this in a
first working version of the code.
32 Hello from fct1() Hello from fct1() Hello from
fct2() Hello from fct1() Hello from fct2() Hello
from fct2() Bye!
33Using Assertions
- Add assert(0 macro to check the status
- If it fails, the program will be aborted.
int main(void) int a,b,c scanf("dd", a,
b) cf(a,b) assert(cgt0) ..
includeltassert.hgt includeltstdio.hgt int f(int
a, int b) int g(int c)
34Scope Rules
- Rule of scope is that identifiers are accessible
only within the block in which they are declared.
They are unknown outside the boundaries of the
block.
35 int a2 printf("d\n",a) int a5
printf("d\n",a) printf("d\n",a)
outer
inner
36 int a1, b2,c3 printf("3d3d3d\n",
a,b,c) int b 4 float c5.0
printf("3d3d5.lf\n",a,b,c) ab
int c cb printf("3d3d3d\n",a,b,c)
printf("3d3d3d\n",a,b,c)
printf("3d3d3d\n",a,b,c)
37Scope Rules
- blocks can be parallel or nested (one placed in
another) - block exit will release the storage allocation
locally to the block - local variables declared inside the exited block
are no valid (scope rule)
38 int a,b float b float a
39 int a,b float b float a,
b
40Scope Rules
- insert a temporary block can help debugging the
programming error - Delete lter after debugging
static in cnt0 printf( debug cntd
vd\n, cnt,v)
check number of time this block has been called
41Storage Classes
- Every variable and function in C has two
attributes type and storage class - There are four storage classes
auto extern register static
42auto Storage Class
- Variables declared within function bodies are
auto class storage, as default - The auto keyword is seldom used, because auto
class is automatic. - auto variables are always in the scope of a block
auto int a,b,c auto float f
int a,b,c float f
43extern Storage Class
- Variables declared outside any function, the
variables are global and storage is extern class - the global variables are considered to be global
to all functions declared after ithen, and upon
exit from the block or function, the external
variables remain in existence.
44 include ltstdio.hgt int a 1, b 2, c 3
/ global variables / int f(void)
/ function prototype / int
main(void) printf("3d\n", f())
/ 12 is printed / printf("3d3d3d\n", a,
b, c) / 4 2 3 is printed / return 0
45int f(void) int b, c
/ b and c are local /
/ global b, c are masked / a b
c 4 return (a b c)
Result
12 4 2 3
46extern Storage Class
- In ANSI C, you could add extern (optional), when
define global variables outside any function,
such as - However, you can even create global (extern
variables within blocks or functions) - being declared in a block that encompasses the
whole program
extern int a1, b2, c3
47include ltstdio.hgt int a 1, b 2, c 3
/ external variables / int f(void) int
main(void) printf("3d\n", f())
printf("3d3d3d\n", a, b, c) return 0
48int f(void) extern int a /
look for it elsewhere / int b, c
a b c 4 return (a b c)
In extern folder, submit the following
commands make a.out 12 4 2 3
49extern Storage Class
- extern (global variable never deleted, they exit
throughout the execution life. - They can be used to transmit variables across
functions - All function definitions are external storage. We
explicitly do
extern double sin(double x)
50register Storage Class
- storage class register tells the compiler that
the associated variables should be stored in
high-speed memory registers - Use register class to declare variable can
improve execution speed. - When speed is a concern, the programmer may
choose a few variables that most frequently
accessed and declared them to be of storage class
register - loop variable and function parameters
51 register int i for (i0 iltLIMIT i)
/blobk exit will free the register
/
register i register int i
default as int
52static Storage Class
- Two distinct uses
- More elementary use is to allow a local variable
to retain its previous value when the block is
re-entered. It is contact to ordinary automatic
variable, which upon the scope rule. - Second use is to connect with external
declaration - For the first use, we have an example
53void f(void) static int cnt0 cnt if
(cnt20) else
First time the f() is called, cnt is initialized
as zero on function exit, the value of cnt is
preserved in memory. Whenever the function is
invoked again, cnt is not re-initalized, it
retain its previous value from the last update,
when the f() is called.
It should be noted that the variable cnt is
declared inside the f() function, which keeps it
privacy to f(). That means, cnt can only be
accessed inside the function f(). In other words,
if it were declared outside of the function, then
other functions could access it.
54static External Variables
- The second use
- is connection with external declarations.
- although they are in external storage. They still
have partial scope rule, upon the position of
functions or block. - difference between static external variables and
regular external variables regular (global
variables) is that static external variables are
scope-restricted external variables
55static External Variables
- The second use
- They are unavailable to functions define earlier
in the file or to functions defined in other
files, even if these functions attempt to use the
extern storage class keyword. - example
56void f(void) static int v void
g(void)
void f(void) int v void g(void)
v is not available here
static external variable
external variable
v is available here
57Example of using static external variable
define INITIAL_SEED 17 define MULTIPLIER
25173 define INCREMENT 13849 define
MODULUS 65536 define FLOATING_MODULUS
65536.0 static unsigned seedINITIAL_SEED unsign
ed random(void) seed(MULTIPLIERseedINCREMENT)
MODULUS return seed
58double probability(void) seed(MULTIPLIERseedI
NCREMENT)MODULUS return (seed/FLOATING_MODULUS)
59static External Variables
- The function random() produces an apparently
random sequence of integer values between 0 and
MODULUS. The function probability() produces an
apparently random sequence of floating values
between 0 and 1. - Call either random() or probability() produces a
new value of the variable seed that depends on
its old value. - Because seed is a static external variable, it is
private to this file, and its value is preserved
between function calls. We can now create
functions in other files that invoke these
random-number generators without worrying about
side effects.
60static External Functions
- static can be used to declare static functions
and function prototypes - Use static to cause the scope of the function to
be restricted within the file in which it is
defined. - It provides the private modules of function
definitions
61static function prototype
static int g(void) void f (int a) static
int g(void)
regular non-static function
static function definition
62Default Initialization
- both external variables and static variables,
that are not explicitly initialized by the
programmers, are initialized to zero by the
system. This includes arrays, string, pointers,
structures, and unions (for each element of
members). - For regular automatic variable and register
variables, usually are not initialized by the
system. - They start with garbage values. Some system does
initialize everything by zero. But do not rely on
that. Programmers should initialize them
explicitly. This needs to be paid special
attention!
63Recursion
- A function is said to be recursive, if it calls
itself, either directly, or indirectly. That
function is called recursive function.
includeltstdio.hgt int main(void) printf("Never
ends") main() return 0
int sum(int n) if (nlt1) return n else
return (nsum(n-1))
123n
64Recursion
0!1, n!n(n-1)!n(n-1)(n-2)32 1
int factorial(int n) if (nlt1) return
1 else return nfactorial(n-1))
recursive version
65Recursion
0!1, n!n(n-1)!n(n-1)(n-2)32 1
int factorial(int n) int product1 for (
ngt1 --n) productn return product
iterative version
66/ Write a line backwards. / include
ltstdio.hgt void wrt_it(void) int
main(void) printf("Input a line ")
wrt_it() printf("\n\n") return 0
67 void wrt_it(void) int c if ((c
getchar()) ! '\n') wrt_it()
putchar(c)
Result
Input a line I like to learn functions in
C. .C ni snoitcnuf nrael ot ekil I
68Efficiency of Recursive Function
- both iterative and recursive algorithms work
sometimes - Typically recursion is more elegant and requires
fewer variables to make the same calculation. - Fibonacci sequence
f00, f11, f i1f if i-1
69int fibonacci(int n) if (nlt0) return
n else return fibonacci(n-1)
fibonacci(n-2))
Easy to write, costly. Do performance study.
70Example Hanoi problem
include ltassert.hgt include ltstdio.hgt include
ltstdlib.hgt extern int cnt / count
of the number of moves / int
get_n_from_user(void) void move(int n, char a,
char b, char c)
71include "hanoi.h" int cnt 0
/ count of the number of moves / int
main(void) int n
/ number of disks / n
get_n_from_user() assert(n gt 0) / //
Move n disks from tower A to tower C, // using
tower B as an intermediate tower. /
move(n, 'A', 'B', 'C') /
recursive fct / return 0
72include "hanoi.h" int get_n_from_user(void)
int n printf("s", "---\n"
"TOWERS OF HANOI\n" "\n" "There are
three towers A, B, and C.\n" "\n"
"The disks on tower A must be moved to tower C.
Only one\n" "disk can be moved at a time,
and the order on each tower\n" "must be
preserved at each step. Any of the towers A,
B,\n"
73 "or C can be used for intermediate placement of
a disk.\n" "\n" "The problem starts
with n disks on Tower A.\n" "\n"
"Input n ") if (scanf("d", n) ! 1 n lt
1) printf("\nERROR Positive integer not
found - bye!\n\n") exit(1)
printf("\n") return n
74include "hanoi.h" void move(int n, char a, char
b, char c) if (n 1) cnt
printf("5d sdscsc.\n", cnt,
"Move disk ", 1, " from tower ", a, " to tower ",
c) else move(n - 1, a, c, b)
cnt printf("5d sdscsc.\n",
cnt, "Move disk ", n, " from tower ", a,
" to tower ", c) move(n - 1, b, a, c)
75CC cc CFLAGS -Wall EXEC
a.out INCLS LIBS OBJS main.o
get.o move.o (EXEC) (OBJS) _at_echo
"linking ..." _at_(CC) (CFLAGS) -o
(EXEC) (OBJS) (LIBS) (OBJS) hanoi.h
(CC) (CFLAGS) (INCLS) -c .c relink
_at_echo "relinking ..." _at_(CC)
(CFLAGS) -o (EXEC) (OBJS) (LIBS)
76--- TOWERS OF HANOI There are three towers A,
B, and C. The disks on tower A must be moved to
tower C. Only one disk can be moved at a time,
and the order on each tower must be preserved at
each step. Any of the towers A, B, or C can be
used for intermediate placement of a disk. The
problem starts with n disks on Tower A. Input n
3
77 1 Move disk 1 from tower A to tower C. 2
Move disk 2 from tower A to tower B. 3 Move
disk 1 from tower C to tower B. 4 Move disk
3 from tower A to tower C. 5 Move disk 1
from tower B to tower A. 6 Move disk 2 from
tower B to tower C. 7 Move disk 1 from tower
A to tower C.