5

我写了这个qsort:

void qsort(void *a[],int low,int high, int (*compare)(void*,void*));

当我打电话时

char *strarr[5];

它说从 char** 到 void** 的无效转换。为什么这是错误的?

这是代码:

#include<cstdlib>
#include<cstdio>
#include<iostream>

using namespace std;

inline void strswap(void *a,void *b) {
    char *t=*(char**)a;
    *(char**)a=*(char**)b;
    *(char**)b=t;
}

int strcompare(void *a, void *b) {
    return strcmp(*(char**)a,*(char**)b);
}

void qsort1(void *a[],int low,int high, int (*compare)(void*,void*), void (*swap)(void*,void*)) {
    if(low>=high)
        return;
    int q=low-1;
    for(int i=low;i<=high-1;i++)
        if((*compare)(&a[i],&a[high]) < 0)
            swap(&a[i],&a[++q]);
    swap(&a[high],&a[++q]);
    qsort1(a,low,q-1,compare,swap);
    qsort1(a,q+1,high,compare,swap);
}

int main() {
    const  int n=3;
    //int a[n]={4,6,8,12,10,9,8,0,24,3};
    char *strarr[5]={"abcd","zvb","cax"};
    qsort1(strarr,0,n-1,strcompare,strswap);
    for(int i=0;i<n;i++)
        cout << strarr[i] << " ";
    cout << endl;
    return 0;
}
4

2 回答 2

12

允许从任何指针类型到的隐式转换void *,因为void *它被定义为具有足够范围的指针类型,它可以表示任何其他指针类型可以表示的任何值。(从技术上讲,只有其他对象指针类型,不包括指向函数的指针)。

但是,这并不意味着它void *具有与任何其他指针类型相同的大小或表示形式:将指针从另一种指针类型转换为 avoid * 并不一定会使底层表示形式保持不变。从double *tovoid *转换就像从doubleto转换一样int- 它必须在编译器的全视图中发生,您不能在编译器背后隐藏该转换。

所以这意味着 whilevoid *是一个通用指针,不是void **一个通用的指向指针的指针。它是一个指向的指针——一个指针应该只指向真实的对象(而它本身可以指向任何东西)。void *void **void *void *

这就是为什么 and 之间没有隐式转换的原因 - 与 and 之间没有隐式转换的type **原因void **相同。double *int *

现在,有一种特殊情况:由于历史原因,char *保证与void *. 这意味着char **(特别是)和之间的转换void **实际上是可以的,作为一般规则的例外。因此,在您的特定void **情况下,如果您在传递strarr到时添加强制转换,则您的代码是正确的qsort1()

但是,您qsort1()仅被定义为正确处理void *or char *(包括unsigned char *等)的数组。例如,您不能使用它对double *指针数组进行排序(尽管它实际上可以在当今最常见的环境中使用)。

于 2010-04-13T04:17:01.770 回答
10

任何指针都可以隐式转换为 void 指针。但是您的第一个参数不是void 指针 - 它是一个 void 指针数组,并且没有隐式转换。您可能希望将您的函数声明为:

void qsort(void *,int low,int high, int (*compare)(void*,void*));

但是不看代码很难说。

于 2010-04-12T12:06:03.703 回答