7.7 Pointers to Pointers
Sometimes it is desirable to pass a pointer to a function and to change the value of the pointer itself; that is, to change what it points to. This can be done using a pointer-to-a-pointer as in the following (rather contrived) example.
void func(int **pptr, int i, int j)
{
if (i<j) *pptr = &i;
else *pptr = &j;
}
This concept may be applied further, so that we can have a pointer-to-a-pointer-to-a-pointer, and so on. But such constructions are rarely necessary.
Changing the value of a pointer inside a function is just one application of pointers-to-pointers.
More frequently they appear in relation to arrays of pointers, which are addressed in Section 8.4.
7.8 Function Pointers
In C, a function is not itself a variable, but it is possible to define pointers to work, which can be assigned, placed in the array, tasks are passed, returned from the works, and so on [KR88, page 118].
Function pointers are a very useful mechanism for selecting, substituting or grouping together functions of a particular form. For example, they may be used to pass functions as arguments to other functions. Or, they may be collected into an array of function pointers as a “dispatch table”, where a certain function is invoked based on an array index.
The declaration of a function pointer must specify the number and type of the function arguments and the function return type. For example, the following declaration is a pointer to a function that has a double and an int argument and returns a double.
double (*pf)(double, int);
Thus, it is not possible to define a completely generic function pointer, only one that points to a certain category of function that fits the declaration.
Notice the use of parentheses around the identifier (*pf). This is necessary to distinguish a pointer-to-a-function from a function-that-returns-a-pointer.
int (*pf)(char); /* pointer-to-function: input char, return int */
int *f(char); /* function: input char, return pointer-to-int */
In a function declaration, it is possible to declare a function pointer without using an identifier; (this is the case also with any other function argument).
void myfunc(char *, int, unsigned (*)(int));
However, it is usually better practice to include identifiers in function prototypes, as it improves readability.
void myfunc(char *message, int nloops, unsigned (*convert)(int));
The following example program uses function pointers to pass functions as arguments to another function. This allows the the latter function to perform a variety of operations without any change to its own algorithm. (Note that, like the array, the function names are automatically converted into pointers without using the address-off operator &.)
1 #include <stdio.h>
2 #include <assert.h>
3
4 double add(double a, double b) { return a + b; } 5 double sub(double a, double b) { return a − b; }
6 double mult(double a, double b) { return a * b; }
7 double div(double a, double b) { assert(b != 0.0); return a / b; }
8
9 void execute operation(double (*f)(double,double), double x, double y)
10 {
11 double result = f(x,y);
12 printf("Result of operation on %3.2f and %3.2f is %7.4f\n", x, y, result);
13 }
14
15 int main(void)
16 {
17 double val1=4.3, val2=5.7;
18 execute operation(add, val1, val2);
19 execute operation(sub, val1, val2);
20 execute operation(mult, val1, val2);
21 execute operation(div, val1, val2);
22 }
Function Pointer can be used to separate some sub-algorithmic functions from within the general purpose main algorithm. It allows the sub algorithm to be swap in or out at the time of running. A common example is a general sorting algorithm that uses function pointer to implement its sorting criteria.
void generic_sort(int *array, int len, int (*compare)(int, int));
int greater_than(int a, int b) { return a > b; } /* Possible sorting criterion. */ int less_than(int a, int b) { return a < b; } /* Possible sorting criterion. */
generic_sort(values, 20, less_than); /* Using the sort algorithm. */
No comments:
Post a Comment