Starting the Visual C IDE

Chapter 10 - Using Pointers

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

Pointers to Functions
All the examples so far have shown you how various items of data can be referenced by a pointer. As it turns out, you can also access portions of code by using a pointer to a function. Pointers to functions serve the same purpose as do pointers to data; that is, they allow the function to be referenced indirectly, just as a pointer to a data item allows the data item to be referenced indirectly.
A pointer to a function can have a number of important uses. For example, consider the qsort( ) function. The qsort( ) function has as one of its parameters a pointer to a function. The referenced function contains the necessary comparison that is to be performed between the array elements being sorted. qsort( ) has been written to require a function pointer because the comparison process between two elements can be a complex process beyond the scope of a single control flag. It is not possible to pass a function by value—that is, pass the code itself. C/C++, however, does support passing a pointer to the code, or a pointer to the function.
The concept of function pointers is frequently illustrated by using the qsort( ) function supplied with the compiler. Unfortunately, in many cases, the function pointer is declared to be of a type that points to other built-in functions. The following C and C++ programs demonstrate how to define a pointer to a function and how to “roll your own” function to be passed to the STDLIB.H function qsort( ). Here is the C program:
/*
*   fncptr.c
*   A C program illustrating how to declare your own
*   function and function pointer to be used with qsort( )
*   Copyright (c) Chris H. Pappas and William H. Murray, 1998
*/

#include <stdio.h>
#include <stdlib.h>

#define IMAXVALUES 10

int icompare_funct(const void
*iresult_a, const void *iresult_b);
int (
*ifunct_ptr)(const void *, const void *);

void main( )
{
 int i;
 int iarray[IMAXVALUES]={0,5,3,2,8,7,9,1,4,6};

 ifunct_ptr=icompare_funct;
 qsort(iarray,IMAXVALUES,sizeof(int),ifunct_ptr);
 for(i = 0; i < IMAXVALUES; i++)
   printf(“%d ”,iarray[i]);
}

int icompare_funct(const void
*iresult_a, const void *iresult_b)
{
 return((
*(int *)iresult_a) - (*(int *) iresult_b));
}
The function icompare_funct( ) (which will be called the reference function) was prototyped to match the requirements for the fourth parameter to the function qsort( ) (which will be called the invoking function).
To digress slightly, the fourth parameter to the function qsort( ) must be a function pointer. This reference function must be passed two const void * parameters and it must return a type int. Remember that the position of the const keyword, in the formal parameter list, locks the data pointed to, not the address used to point. This means that even if you write your compare routine so that it does not sort properly, it can in no way destroy the contents of your array! This is because qsort( ) uses the reference function for the sort comparison algorithm. Now that you understand the prototype of the reference function icompare_funct( ), take a minute to study the body of the reference function.
If the reference function returns a value < 0, then the reference function’s first parameter value is less than the second parameter’s value. A return value of zero indicates parameter value equality, with a return value > 0 indicating that the second parameter’s value was greater than the first’s. All of this is accomplished by the single statement in icompare_funct( ):
return((*(int *)iresult_a) - (*(int *) iresult_b));
Since both of the pointers were passed as type void *, they were cast to their appropriate pointer type int * and then dereferenced (*). The result of the subtraction of the two values pointed to returns an appropriate value to satisfy qsort( )’s comparison criterion.
While the prototype requirements for icompare_funct( ) are interesting, the meat of the program begins with the pointer function declaration below the icompare_funct( ) function prototype:
int icompare_funct(const void *iresult_a, const void *iresult_b);
int (
*ifunct_ptr)(const void *, const void *);
A function’s type is determined by its return value and argument list signature. A pointer to icompare_funct( ) must specify the same signature and return type. You might therefore think the following statement would accomplish this:
int *ifunct_ptr(const void *, const void *);
That is almost correct. The problem is that the compiler interprets the statement as the definition of a function ifunct_ptr( ) taking two arguments and returning a pointer of type int *. The dereference operator unfortunately is associated with the type specifier, not ifunct_ptr( ). Parentheses are necessary to associate the dereference operator with ifunct_ptr( ).
The corrected statement declares ifunct_ptr( ) to be a pointer to a function taking two arguments and with a return type int that is, a pointer of the same type required by the fourth parameter to qsort( ).
In the body of main( ), the only thing left to do is to initialize ifunct_ptr( ) to the address of the function icompare_funct( ). The parameters to qsort( ) are the address to the base or zeroth element of the table to be sorted (iarray), the number of entries in the table (IMAXVALUES), the size of each table element (sizeof(int)), and a function pointer to the comparison function (ifunct_ptr( )).
The C++ equivalent follows:
//
//  qsort.cpp
//  A C program illustrating how to declare your own
//  function and function pointer to be used with qsort( )
//  Copyright (c) Chris H. Pappas and William H. Murray, 1998
//

#include <iostream.h>
#include <stdlib.h>

#define IMAXVALUES 10

int icompare_funct(const void
*iresult_a, const void *iresult_b);
int (
*ifunct_ptr)(const void *,const void *);

void main( )
{
 int i;
 int iarray[IMAXVALUES]={0,5,3,2,8,7,9,1,4,6};

 ifunct_ptr=icompare_funct;
 qsort(iarray,IMAXVALUES,sizeof(int),ifunct_ptr);
 for(i = 0; i < IMAXVALUES; i++)
   cout <<“[{||}]” << iarray[i];
}

int icompare_funct(const void
*iresult_a, const void *iresult_b)
{
 return((
*(int *)iresult_a) - (*(int *)iresult_b));
}
Learning to understand the syntax of a function pointer can be challenging. Let’s look at just a few examples. Here is the first one:
int *(*(*ifunct_ptr)(int))[5];
float (
*(*ffunct_ptr)(int,int))(float);
typedef double (
*(*(*dfunct_ptr)( ))[5])( );
 dfunct_ptr A_dfunct_ptr;
(
*(*function_ary_ptrs( ))[5])( );
The first statement defines ifunct_ptr( ) to be a function pointer to a function that is passed an integer argument and returns a pointer to an array of five int pointers.
The second statement defines ffunct_ptr( ) to be a function pointer to a function that takes two integer arguments and returns a pointer to a function taking a float argument and returning a float.
By using the typedef declaration, you can avoid the unnecessary repetition of complicated declarations. The typedef declaration (discussed in greater detail in Chapter 13) is read as follows: dfunct_ptr( ) is defined as a pointer to a function that is passed nothing and returns a pointer to an array of five pointers that point to functions that are passed nothing and return a doubles.
The last statement is a function declaration, not a variable declaration. The statement defines function_ary_ptrs( ) to be a function taking no arguments and returning a pointer to an array of five pointers that point to functions taking no arguments and returning integers. The outer functions return the default C and C++ type int.
The good news is that you will rarely encounter complicated declarations and definitions like these. However, by making certain you understand these declarations, you will be able to confidently parse the everyday variety.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net