CPS188
Computer Programming Fundamentals
Lesson 06
Pointers and Modular Programming
(Chapter 6)
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 1
Chapter Objectives
● To learn about pointers and indirect
addressing.
● To learn how to return function results
through a function’s arguments.
● To understand the differences between
call-by-value and call-by-reference.
● To understand the distinction between
input, in/out, and output parameters and
when to use each kind.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 2
Variables and Memory
● Each variable used in C is stored at a specific
address in the computer's memory.
● We do not really know or care what that
address is but it is important for the operating
system.
● The & operator provides us with the actual
address of the variable in memory.
○ For example, by declaring int x; I create a
variable named x. This variable is stored at
the address &x in the computer's memory.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 3
Pointer Variables
● We know that the address of x can be
represented by &x. It is possible to put such an
address into a variable (known as a pointer
variable or simply pointer).
● A pointer is in fact a variable that contains the
address of another variable.
● A pointer variable type can be int*, char*, or
double*, meaning respectively pointer-to-int,
pointer-to-char, and pointer-to-double. The type
of the pointer must match the type of the
variable it points to.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 4
Pointer Variables
● Let's have an example:
int x = 10;
int* ptr;
ptr = &x;
● In the third instruction, we place the address of x
into the pointer variable ptr. It is now stated that
ptr points to x.
● The variable ptr, however, must be of a special type
ready to hold addresses, specifically addresses of
integers (since x is int). So to declare ptr we use
the int* type (pointer to integer).
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 5
Pointer Variables
● Note that since spacing is often not taken into
account in C,
int* ptr; can be written as int * ptr; or int *ptr;
● The * operator gets the value of the variable
pointed by the pointer variable. It is not the same *
as in the declaration. It is an executable operator.
● The * operator can only be applied to a pointer
variable, not a value variable. *ptr will follow the
arrow to the variable x and reveal its value. So, *ptr
is really x. ptr x
⚫ 10
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 6
Pointer Variables
● *ptr means: Go to ptr > Follow the arrow > Get
the value. printf ("%d", *ptr); displays 10.
● There is a %p placeholder for printing the
actual address stored in a pointer variable
(only a curiosity really).
● printf ("%p", ptr); will display a memory
address in hexadecimal like 0x7ffe34bb337c.
● When using the debugger in OnlineGDB you
can see the values (addresses) stored in the
pointer variables.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 7
Why Pointers?
● Pointers are not that intimidating and are not
that hard to understand. They are an integral
part of what the C programming language is all
about.
● A few practical uses of pointers in C:
○ To have a function give more than one result.
○ To have a function that accepts arrays and
gives arrays as results.
○ To manage advanced data structures like
linked lists, stacks, queues and trees.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 8
Don't Be Afraid of Pointers!
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 9
Functions with Multiple Results
● We know that functions can only have one
result (one return statement), but we can
trick a function into giving multiple results
by using pointer parameters.
● Let's have a function that takes in a
double number and gives back 3 “results”: a
sign, a whole part, and a fraction.
–
–3.1416 3
0.1416
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 10
Functions with Multiple Results
● The best thing to do next is to analyze our
function by making a diagram of what goes in and
of what comes out by labelling everything properly
with their types.
char sign
int whole
double number split
double fraction
● Notice the 3 arrows on the right side. Since a
function can only have 1 true result, we will have
to do something about the two extra results.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 11
Functions with Multiple Results
● Of course, our function can only have one
true result (one return), so we'll pick one (any
one will do). Let's pick the sign as the result.
Since the sign is a character, our function
will be a char function (the type of the
result).
● The two other expected “results” (the whole
part and the fraction) will be made accessible
to the main program by pointer parameters.
The diagram on the next slide shows the
outcome.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 12
Functions with Multiple Results
● To get rid of the extra results, we will pick one
as the "true" result and the other two will be
"fake" results. We then transfer the "fake"
results to the left side but as pointers (we
simply add a * in front of their names).
● Now our function has only one result, hence
perfectly legal.
double number
char sign
int *whole split
double *fraction
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 13
Functions with Multiple Results
char
split (double number, int *whole, double *fraction)
{
char sign;
if (number < 0) *fraction and
sign = '-'; *whole are
else actually f and w
if (number > 0) from the main
program (see next
sign = '+'; slide)
else
sign = ' ';
*whole = abs ((int)number);
*fraction = fabs (number) - *whole;
return (sign);
}
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 14
Functions with Multiple Results
int
main (void) When a
parameter is a
{ pointer, you must
double n, f; send an address
int w; value to it.
char s;
printf ("Enter a double number:");
scanf ("%lf", &n);
s = split (n, &w, &f);
printf ("The sign is: %c\n", s);
printf ("The whole part is: %d\n", w);
printf ("The fraction is: %lf\n", f);
return (0);
}
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 15
Functions with Multiple Results
● As you can see with the following order function
(see link below), you can also move all the results to
the left side, therefore leaving no output and no
result, hence a void function.
[Link]/programming/c/[Link]?chap=06&pgm=12
double *small
double *big order
void order (double *small, double *big)
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 16
Scope of Names
● The scope of a variable or function name is the region
in a program where a particular variable is visible.
● Variables are limited in scope inside the function in
which they are declared including parameters and
variables in the main program.
double f1(int var1, double var2){ ➩ var1, var2 and var3 only exist
int var3; inside the f1 function.
. . .
} ➩ var4, var5 and var1 only exist
inside the f2 function (this var1 is
int f2(int var4, char var5){ not the same as the one in f1).
int var1;
. . . ➩ var6 and var4 only exist inside
} the main program (this var4 is not
the same as the one in f2).
int main(void){
int var6,var4; ➩ f1 is visible from f2 and main
. . . but f2 is only visible from main.
}
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 17
Function Pointers
● A function pointer is a type of pointer that
stores the address of a function, allowing
functions to be passed as arguments and invoked
dynamically.
● It is useful in techniques such as callback
functions, event-driven programs, and
polymorphism (a concept where a function or
operator behaves differently based on the
context).
● In a way it can simulate object-oriented
programming in C albeit imperfectly.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 18
Function Pointers
● Here in an example of a simple function.
int add (int a, int b) {
int c;
c = a + b;
return (c); }
● In the main program you declare a pointer to the
function. Syntax is ftype (*pvariable) (types of
the inputs).
int (*fptr)(int, int);
● Then you assign the function name to the pointer
and use it. It is like a function alias.
fptr = add;
printf ("%d\n", fptr(40,60); 100
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 19
Function Pointers
● This program presents a simple example of
polymorphism.
#include <stdio.h>
int add(int a, int b) {
return (a + b);
}
int subtract(int a, int b) {
return (a - b);
}
int main(void) {
int (*operation)(int, int);
operation = add;
printf("Result of addition: %d\n", operation(5, 3));
operation = subtract;
printf("Result of subtraction: %d\n", operation(5, 3));
return (0); }
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 20
A Function as Another Function Parameter
● You can also put a function header into the parameter
list of another function. This example will work with any
one-argument double function.
#include <stdio.h>
#include <math.h>
// evaluates a function with one argument
void
evaluate(double f(double f_arg), double pt1, double pt2, double pt3) {
printf("f(%.5lf) = %.5lf\n", pt1, f(pt1));
printf("f(%.5lf) = %.5lf\n", pt2, f(pt2));
Square Root
printf("f(%.5lf) = %.5lf\n", pt3, f(pt3));
} f(25.00000) = 5.00000
f(49.00000) = 7.00000
int main (void) { f(16.00000) = 4.00000
printf ("Square Root\n");
evaluate (sqrt, 25.0, 49.0, 16.0); Decimal Log
f(25.00000) = 1.39794
printf ("\nDecimal Log\n"); f(49.00000) = 1.69020
evaluate (log10, 25.0, 49.0, 16.0); f(16.00000) = 1.20412
return (0);
}
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 21
A Function as Another Function Parameter
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 22
Bisection Method for
Finding Equation Roots
A Case Study
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 23
The Bisection Method
● The bisection method is one of the simplest
computer programming approach to find the
solution of nonlinear equations. It requires two
initial guesses, a tolerance level and a maximum
number of iterations.
● Let's find a root of the nonlinear function
x3–4x–9. The initial guesses are a and b. The
calculation is done until the following condition is
satisfied: |a-b| < 0.0005 or if (a+b)/2 < 0.0005
(or both equal to zero) where, (a+b)/2 is the
middle point value.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 24
Bisection Method Algorithm
1. Define a function that finds the root of the
equation. You expect the root to be between the two
guesses.
2. Write a loop to find the root of the equation.
a. Use the bisection method to find the root.
b. Print the root of an equation.
☞ The algorithm finds one root between the two
guesses. To find more roots, you need to call the
function more than once with different guesses.
The program: [Link]
Reference [not required reading]: [Link]/wiki/Bisection_method
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 25
Debugging and Testing a Program System
● Unit (Function) Testing
○ Test the smallest testable piece of the
software, a single function.
○ Write a short main program that calls only
the function to be tested (called a driver).
○ The program sends arguments to the
function parameters.
○ After calling the function, the program
should display the function results.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 26
Debugging and Testing a Program System
● System Testing
○ Test the whole program in the context in
which it will be used.
○ A program may need to be tested with
other programs and hardware.
● Acceptance Testing
○ Shows that the program meets its
functional requirements. Typically involves
use of the system in the real environment
or in a close approximation to the real
environment.
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 27
End of lesson
Copyright ⓒ Dr. Denis Hamelin, Toronto Metropolitan University.
Copyright ⓒ Jeri R. Hanly & Elliot B. Koffman, Pearson Education Inc. 28