Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use of a pointer to function as shown in K&R example

In the K&R ANSI C book I have stumbled upon a piece of code where a pointer to a function is used. I think I understand the idea behind pointers to functions, but the example presented in the book does not make sense to me.

The function is to sort lines of text using quicksort sorting algorithm. The declaration of quicksort function looks like this:

void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *);

This so far makes perfect sense to me, we are declaring a function where one of the arguments is a pointer to a function (comp) with two void pointer arguments. I assume we are doing it this way to save memory, and not make copies of actual function.

Later on the function is used in main in this way:

qsort((void **) lineptr, 0, nlines-1, (int (*)(void*, void*))(numeric ? numcmp : strcmp));

Here is where I have some questions:

  1. why is lineptr cast to (void **)
  2. what is the use of using (numeric ? numcmp : strcmp), does it mean that pointers to functions can also be assigned like this: int ( * )(void*, void*) numcmp

EDIT: The lineptr is defined like this: char *lineptr[MAXLINES]; I assume we are casting void** to change it from char to type void pointer

like image 622
Damian Kowalski Avatar asked Dec 17 '22 12:12

Damian Kowalski


1 Answers

The K&R book predates standardized C, so some constructs which were valid at the time are no longer valid. Specifically, it seems to be assuming that conversion between any two pointer types is valid.

lineptr is an array of char *, and this array will decay into a pointer to its first element when used in an expression, i.e. char **. So the cast to void ** is needed to match the argument type, as only a conversion to/from void * may be performed without a cast.

The expression (numeric ? numcmp : strcmp) is choosing a function to pass as the comp parameter to the function, so either numcmp or strcmp depending on the value of numeric. The cast to (int (*)(void*, void*)) is needed because strcmp (and presumably numcmp) has type int (*)(const char *, const char *).

Casting to a different function pointer type and subsequently calling the function using the casted type is undefined behavior in standard C, however it was probably allowed in K&R C.

like image 129
dbush Avatar answered Dec 20 '22 02:12

dbush