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 *。ポインタを別のポインタ型からに変換してもvoid * 、基になる表現が変更されないままになるとは限りません。からへの変換は、からdouble *へのvoid *変換と同じです。コンパイラの全体像で行う必要があり、その変換をコンパイラの背後に隠すことはできません。doubleint

つまり、これvoid *は、がジェネリックポインターであり、ジェネリックポインターツーポインターでvoid **ないことを意味します。これはへのポインタですvoid *-ポインタは実際のオブジェクトvoid **のみを指す必要があります(それ自体は何でも指すことができます)。void *void *

これが、との間に暗黙の変換がない理由です。これは、との間type **に暗黙の変換void **がないのと同じ理由です。double *int *

ここで、1つの特殊なケースがあります。歴史的な理由から、char *と同じサイズ、表現、および配置要件を持つことが保証されていますvoid *。これは、一般的な規則の例外として、char **(特に)との間の変換は実際にはOKであることを意味します。void **したがって、特定void **のケースでは、に渡すときににstrarrキャストを追加すると、コードは正しくなりますqsort1()

ただし、またはの配列(などを含む)qsort1()で正しく機能するように定義されているだけです。たとえば、ポインタの配列を並べ替えるために使用することはできません(ただし、実際には、今日のほとんどの一般的な環境で機能します)。void *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 に答える