3
votes

I have similar "generic" procedure like qsort, which has a void pointer (pointing at an array) and also a function pointer parameter. This function should work on any type of array.

Example:

void do_something(void * array, int count, int size, void (*test)(const void*)){
    int i;
    for(i=0; i<count; i++){
        test(array + (index * size));
    }
}

This however gives me the following warning (gcc test.c -pedantic-errors):

error: pointer of type ‘void *’ used in arithmetic [-Wpedantic]

And after some research I found out it's a bad practice to use void pointers like this. (E.g. Pointer arithmetic for void pointer in C)

So how does the standard library do this kind of stuff for like qsort? Looking at this code: (http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c), I see the following:

void
_quicksort (void *const pbase, size_t total_elems, size_t size,
        __compar_fn_t cmp)
{
  register char *base_ptr = (char *) pbase;
  ....
  char *lo = base_ptr;
  char *hi = &lo[size * (total_elems - 1)];
  ...
}

Are they casting to (char *) regardless of the actual type?

3
Well using char is not more regardless of type than using void :) Arthmetic on char do the job (move with size steps).hexasoft

3 Answers

3
votes

i asked similar question Can I do arithmetic on void * pointers in C?.

Void * arithmetic is not defined. What does it mean to add 1 to a void pointer ? Most compilers (if they allow it) treat it as incrementing by sizeof(char) ("the next byte") but warn you.

So the right thing to do is to explicitly make it do what you want -> cast to char* and increment that

1
votes

Pointer arithmetic on incomplete data type void is not legal and that is what the compiler is complaining.

As you can see in the _quicksort() the pointer is a constant one so that you can't modify the address the pointer is pointing to. There is no arthmetic operation happening on the void pointer.

1
votes

Making a pointer void just takes away the "context" of the pointer - That is, how the system should look at the pointer or whatever the pointer is holding.

For this reason, compilers do not do arithmetic on void pointers. In order to do pointer arithmetic, the compiler needs to know the type of the pointer such that it can do the proper conversions (if the pointer holds an int, it will not do an addition of with 32 bits or at least it will let you know something is gone awry!).

For this reason, the only way to do this is to cast the pointer to something and do it - I would not recommend it unless you know very well what the pointer is getting. Void pointers are rather very dark programming.