0

Suppose that I had a function in C that accepted as input two void pointers, *a and *b say, as well as a function (as pointer) that itself accepted two void pointers. For example, the function might have a declaration like

arbitrary_type f(void *a, void *b,
                   arbitrary_type (*g)(void *, void *)) 
{
      ...
}

Let's also suppose that the function only acts via the function 'g' (which could be thought of as a sort of getter or setter for the variables pointed to by 'a' and b'.)

Would that function technically be capable of acting on arbitrary triples (a, b, g) of pointers of the form type_a *a, type_b *b, rtype (\*g)(type_a *, type_b *) without introducing errors?

TLDR
  • 103
  • 3
  • You just reinvented [`qsort()`](https://port70.net/~nsz/c/c11/n1570.html#7.22.5.2). So yes, it works. – Andrew Henle Jan 10 '22 at 12:09
  • Re “Would that function technically be capable of acting on arbitrary triples”: No, not quite. Passing pointers to qualified types, such as `const char` or `volatile unsigned`, would introduce some issues. – Eric Postpischil Jan 10 '22 at 12:33

2 Answers2

2

Would that function technically be capable of acting on arbitrary triples (a, b, g) of pointers of the form type_a *a, type_b *b, rtype (\*g)(type_a *, type_b *)

Yes.

without introducing errors?

Oh. Well...that all comes down to the implementation of whatever g is pointing to. Unfortunately, as soon as you use void * for anything, you've thrown any concept of type safety out the window and into oncoming traffic.

This is pretty much how the qsort standard library function works - you pass it a pointer to your array (as a void *), the number of elements, the size of each element, and a pointer to a function that compares two elements:

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

If you want to sort an array of int in ascending order, you write a comparison function like so:

int compare_int( const void *l, const void *r )
{
  const int *a = l;
  const int *b = r;

  if ( *a < *b )
    return -1;
  else if ( *a > *b )
    return 1;

  return 0;
}

int main( void )
{
  int arr[100];
  ...
  qsort( arr, 100, sizeof arr[0], compare_int );
}

We can do the same thing for an array of double:

int compare_dbl( const void *l, const void *r )
{
  const double *a = l;
  const double *b = r;

  if ( *a < *b )
    return -1;
  else if ( *a > *b )
    return 1;

  return 0;
}

int main( void )
{
  double arr[100];
  ...
  qsort( arr, 100, sizeof arr[0], compare_dbl );
}

The compare_int and compare_dbl functions are responsible for converting the arguments to the appropriate type for comparison. But here's the problem - there's nothing stopping you from doing this:

int arr[100];
...
qsort( arr, 100, sizeof arr[0], compare_dbl );

There's no kind of compile-time or run-time check to make sure you've passed the right comparison function for the type of array you're trying to sort. Since both qsort and your comparison functions use void * for everything, there's no way for the compiler to know you're passing the wrong comparison function for the type of the array that you're using.

Yes, you can act on combinations of arbitrary types. No, you can't guarantee that doing so will not introduce any errors.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

Would that function technically be capable of acting on arbitrary triples (a, b, g) of pointers of the form type_a *a, type_b *b, rtype (*g)(type_a *, type_b *)

Yes.

without introducing errors?

Well, that depends on the actual code. Note that void * pointers remove the ability of the compiler to statically check if types of pointers are correct.


It strongly depends on what interface you are modeling, but you can take one void * pointer and let the user "bind" two a b variables together with a struct.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • This answer says "depends on the actual code"; it's too vague in my opinion. Would be better to present examples of correct and incorrect code. Some hints are in [this answer](https://stackoverflow.com/a/11647310/509868) to a similar question, but not good either, because that question is tagged C/C++. – anatolyg Jan 10 '22 at 13:00