Search code examples
cvoid-pointers

How can I pass void pointer to function in C?


I have got sort function. I am passing arguments to this function like this for example:

double tab[] = {-46, -81, 89, -13, -24, -65, 78, -32, -92, -43, 58, -48, 87, 31, 81};
int res = sort(tab, 15, sizeof(double), comp_double);

Then in sort function i want to pass two elements from my tab to compare function. But there is error that pointer of type (void *) used in arithmetic.

typedef int(*f)(const void*, const void*);
int sort(void *ptr, int N, int sizeof_element, f f);

I am writing about this line which is inside sort function:

comp_double((void *)(ptr + j), (void *)(ptr + j + 1))

And my question is how to pass comp_double function concrete numbers from tab. I can't change declarations of my functions.

EDIT: So my comp_double function is good. And as I said, i can't change declarations of my functions. I have to sort array using sort function, so I have to use my comp fucntion. But I don't know how to pass arguments to it.

int comp_double(const void *ptr1, const void *ptr2){
    if(ptr1 == NULL || ptr2 == NULL){
        return 100;
    }
    if(*(double *)ptr1 > *(double *)ptr2){
        return 1;
    }
    else if(*(double *)ptr1 < *(double *)ptr2){
        return -1;
    }
    return 0;
}

int sort(void *ptr, int N, int sizeof_element, f function){
    if(ptr == NULL || N <= 0 || sizeof_element <= 0 || function == NULL){
        return 1;
    }
    if(function == comp_double){
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N - 1; j++){
                if(comp_double((void *)(ptr + j), (void *)(ptr + j + 1)) == 1){
                    double temp = 0;
                    temp = *(double *)(ptr + j);
                    *(double *)(ptr + j) = *(double *)(ptr + j + 1);
                    *(double *)(ptr + j + 1) = temp;
                }
            }
        }
    }
    return 0;
}

This is my error:

comparators.c: In function ‘sort’:
comparators.c:12:45: error: pointer of type ‘void *’ used in arithmetic [-Werror=pointer-arith]
                 if(comp_double((void *)(ptr + j), (void *)(ptr + j + 1)) == 1)

Solution

  • How can I pass void pointer to function in C?

    You already are, so that's not your problem.

    I am writing about this line which is inside sort function:

    comp_double((void *)(ptr + j), (void *)(ptr + j + 1))
    

    OK, it's not passing void* you're having trouble with, but doing pointer arithmetic on it.

    The reason is that there's no type associated with void*, so the compiler doesn't know how many bytes ptr+1 should be advanced. If you were using char *ptr, it would be one byte. For double* ptr it would be sizeof(double) bytes, etc.

    Since we can't cast ptr to the correct type (it can be different on each call, which is what makes the function reusable), we have to do this pointer arithmetic manually instead:

    char *base = (char *)ptr;
    ...
    comp_double(base + j*sizeof_element, base + (j + 1)*sizeof_element);
    

    Notes:

    1. the pointer argument can be implicitly cast back to void*, there's no need to do it explicitly
    2. any pointer T* such that sizeof(T)==1 will work correctly: char is kind of traditional, uint8 is also fine