简体   繁体   English

如何将 void 指针传递给 C 中的函数?

[英]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.但是在算术中使用类型(void *)的指针存在错误。

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.我的问题是如何从选项卡传递 comp_double 函数具体数字。 I can't change declarations of my functions.我无法更改我的函数的声明。

EDIT: So my comp_double function is good.编辑:所以我的 comp_double 功能很好。 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.我必须使用 sort 函数对数组进行排序,所以我必须使用我的 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)

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.使用我要添加的更新代码,您不能直接在sort函数中调用comp_double That is what f is intented to be used for.这就是f的用途。

The error message you get is because you cannot do pointer arithmetics on a void* as void does not have a size.您收到的错误消息是因为您无法对void*进行指针运算,因为void没有大小。 (Except with some GCC extensions) (除了一些 GCC 扩展)

How can I pass void pointer to function in C?如何将 void 指针传递给 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.好的,它不是传递您遇到问题的void* ,而是对其进行指针运算。

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.原因是没有与void*关联的类型,因此编译器不知道ptr+1应该提前多少字节。 If you were using char *ptr , it would be one byte.如果您使用的是char *ptr ,它将是一个字节。 For double* ptr it would be sizeof(double) bytes, etc.对于double* ptr ,它将是sizeof(double)字节等。

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:由于我们无法将ptr转换为正确的类型(每次调用都可能不同,这就是使函数可重用的原因),我们必须手动执行此指针运算:

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指针参数可以隐式转换回void* ,无需显式执行
  2. any pointer T* such that sizeof(T)==1 will work correctly: char is kind of traditional, uint8 is also fine任何指针T*使得sizeof(T)==1可以正常工作: char有点传统, uint8也可以

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM