Home > Blockchain >  How can I pass void pointer to function in C?
How can I pass void pointer to function in C?

Time:05-20

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)

CodePudding user response:

Unfortunately you did not provide enough code to show it in your code. You will need to fill the blanks.

To call the passed compare function, you need to do the arithmetics on your own:

int sort(void *ptr, int N, int sizeof_element, f f)
{
  uint8*p = ptr;
  // ... Doing the sorting things...
  //Assuming you want to compare element j and k in the array
  int result = f( &p[j*sizeof_element], &p[k*sizeof_element] );
  // ... Doing more sorting things
}

With your updated code I want to add, that you mustn't call comp_double directly in the sort function. That is what f is intented to be used for.

The error message you get is because you cannot do pointer arithmetics on a void* as void does not have a size. (Except with some GCC extensions)

CodePudding user response:

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

CodePudding user response:

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.

You should use the correct type in the comparison function:

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

You can then cast the function to the right type for sort: (f)comp_double.

  • Related