2

The following code snippet is from K&R Chapter 5-11: Pointers to Functions:

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

I am able to compile/run the code with (void*) so why is lineptr cast with (void **) instead? Are there any internal differences between the two casts or is it more for readability? Is (void *) casting just the array whereas (void **) is casting both the array and stored pointers?

I understand **lineptr is equivalent to *lineptr[] and the reason for void cast is to make the compiler happy.

Jérôme Teisseire
  • 1,518
  • 1
  • 16
  • 26
Kevin
  • 97
  • 9

1 Answers1

2

It's most likely incorrect.

A void* is a pointer which points to something. We don't know what it points to. You can cast any pointer to a void*. The comparison function that you pass to qsort has to guess what the actual type is that the void* points to. If it gets it right, fine. If it gets it wrong, things will go wrong - that's life and the programmer's responsibility.

A void** is a pointer to an array of void*. There's a big difference here: While you can convert for example an int* to a void* without problems, an array of int* is most definitely not an array of void*. int* and void* can have different sizes! The C Standard makes quite clearly which kinds of pointers have the same representation:

  1. Any variation of void* and char* (void** is not a variation of void*)
  2. Any pointers to structs
  3. Any pointers to unions
  4. Any pointers to primitive types of different signedness (like int, unsigned int).

Any pointers not in the same group can have different representations, so a cast would possibly work, but memcpy or reading the value through a pointer to a differnt pointer type doesn't work.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • When you say it's most likely incorrect, are you referring to the code provided by K&R? – Kevin Dec 26 '14 at 21:11
  • I am reading the one found on [link](http://www.iups.org/media/meeting_minutes/C.pdf), which is the second edition. Also, is the `(void **)` cast only casting the pointers in the array? – Kevin Dec 26 '14 at 21:22