Title: Function Pointers and Code Reuse
1Function Pointers and Code Reuse
- Introduction
- How this is done in an object orientated language
- Generalised sorting
- Customisation approaches for a reusable sort
- An application with 2 sort comparisons
- First design using a reserved global typedef
- Second design using a clean namespace
- Program output
2Introduction
- The 'C' language was designed before the
principles of Object Oriented Programming (OOP)
were widely known. Later programming languages
such as C and Java had OOP design principles
encouraging greater code reuse such as
encapsulation, inheritance and dynamic allocation
of memory as core language design features. - However, those interested in designing system
software can use 'C' efficiently for this in an
object-oriented manner. This approach is likely
to be needed in order to make large projects
manageable due to the increasing complexity of
modern systems and the difficulties older
software-engineering methodologies have had in
coping with this complexity.
3How this is done in object oriented languages
- A Java programmer who creates a simple applet
learns that functionality and data made available
through a publicly-available class package (e.g.
the Java Applet class) can be extended by the
programmer adding methods (the OO name for
functions) which are auto-magically called from
the extended or sub-class whenever the applet
needs to be started, stopped or redrawn. - This makes it possible for complex and
interesting programs to be created which provide
sophisticated graphical user interfaces without
the programmer needing to know very much about
how these details are done. Because the class
package is designed in a reuseable manner the
programmer just needs to know how to write the
functions automatically called which specialise
the more general class as required for the
application.
4Maximising code reuse
- Code reuse is at the heart of OOP. For one
programmer to be able to write code that can be
used by many others this needs to be generalised.
This requires that classes or functions made
available for other programmers through libraries
must be able to handle a very wide variety of
tasks which come within the scope of the
generalised action being performed. - This presentation uses sorting as a generalised
requirement to illustrate the issues involved and
to develop a practical solution using 'C'.
5Generalised Sorting
- The example program below handles a task which
needs to be performed many times on many kinds of
data in many different applications. The sorting
requirement can therefore benefit from reuseable
code. - A sort program has to provide 3 facilities
- An algorithm - the sequencing of actions
- Swapping - exchanging a pair of records or
pointers. - Comparison - comparing 2 records
6The sort algorithm
- Comparisons and swaps are carried out
repetitively until the data is in the required
order. For a fast sort a recursive algorithm such
as quick sort will be used to control this
sequence of operations, but sorting can be
demontrated more simply using non-recursive
algrorithms. - The same algorithm can be applied to many
different array sorting applications. It is
unlikely that the same approach will be suitable
for sorting data stored in entirely different
structures such as files or linked lists.
7Swapping
- Data in dynamic structures is conveniently
swapped by relocating the addresses of the data
while the data can stay in the same place. Data
in arrays is generally swapped directly. - Direct swapping requires that the records be of
the same size and that this size is known. If
addresses or references to variable length data
are in an array, or if the data is stored
directly in an array the swapping operation can
be generalised.
8Comparison
- Data from 2 records are compared to decide
whether or not these records need to be swapped.
This part of the sort operation is application
specific so needs to be customised. Different
sort applications will require comparisons on
different fields or parts of the data to be
carried out in different ways, e.g. ascending,
descending, string and numeric, case sensitive
and insensitive based on different alphabets
(ASCII, Greek, Japanese) etc. Sometimes primary,
secondary and more sort keys are compared.
9Customisation approaches for a reusable sort
- Parameterising the sort function or program
- Cut paste and modify the sorting source code
- Enable the reuser to supply a custom comparison
function
10Parameterising the sort program
- The GNU sort program accepts up to 21 different
command line parameters, of which 15 allow the
user to specify how the comparison is to be
carried out. These allow for alphabetic and
numeric sorts in ascending and descending order
based on specified positions for primary,
secondary and ternary etc. sort fields within
variable and fixed-length data. - Someone using this sort might need to spend an
hour or so reading the documentation and
experimenting the first time it is used, unless
the requirement is very simple (e.g. single field
records) , or the user is already familiar with
Unix style command documentation. The next time
this user is likely to be able to program GNU
sort into a different application more quickly.
11Cut paste and modify older sort code
- A programmer who has already written a sort
function which works in one program can
relatively easily cut and paste the entire
function into another program and modify the
program statement which carries out the
comparison and the type of the temporary record
used for swapping. - This will be quicker if the function is already
suitably parameterised so that it can handle
different array sizes and record lengths. The
downside of cut and pasted code is cut and pasted
bugs and a potential long-term software
maintenance explosion. However, this approach is
valid for disposable code used in throw-away
applications, e.g. for one off data conversions
during a system upgrade.
12Enabling the reuser to supply a comparison
function
- The only part of the sort program likely to need
changing is the part that carries out the
comparison. The application programmer can use
a generalised sort function provided by a library
programmer and supply this sort function with a
customised comparison function. - To achieve this using 'C' the application
programmer supplies the address of the comparison
function as a sort function parameter.
13An application with 2 sort comparisons
- The application will sort student records either
by name or by mark. These 2 sorts are carried out
using the same sort function and passing it the
address of the comparison function to be used. 2
different comparison functions have to be written
to compare by student name or by mark. - The prototype of the gsort (general sort)
function has to include the prototype of the
comparison function as a parameter.
14The function pointer parameter
- int (comp)(RECORD x,RECORD y)
- This is the prototype of the comparison function,
which gsort() will call. The brackets between
the return type of int and the function pointer
int (comp) are needed to indicate that this
parameter of gsort is a function pointer. Without
these brackets the declaration would make the
return type of comp a pointer to int, int rather
than int. The final part of this parameter
(RECORD x,RECORD y) indicates that the function
comp() will require 2 pointers to data type
RECORD as its parameters when comp() is called by
gsort(). These will be the addresses of the 2
records to be compared.
15First typed implementation
- The first implementation of gsort() requires the
user to define a data type called RECORD as this
type is used by gsort() and swap(). This
potentially conflicts if the symbol RECORD is
used for a different purpose within the program.
16First sort with global type 1
17First sort with global type 2
18First sort with global type 3
19First sort with global type 4
20First sort with global type 5
21Second untyped implementation
- The second implementation avoids the requirement
to reserve a global typedef name by casting the
relevant record and array pointers to (void).
The information lost when typed pointers are cast
to void pointers is the record length, so this
information will need to be passed as a separate
parameter in the second version of this program.
22Second sort with void types 1
23Second sort with void types 2
242nd sort with void types 3
25Second sort with void types 4
262nd sort with void types 5