Pergunta

Eu escrevi este qsort:

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

Quando eu chamo isso em

char *strarr[5];

Diz a conversão inválida de char ** para void **. Por que isso está errado?

Este é o código:

#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;
}
Foi útil?

Solução

Uma conversão implícita de qualquer tipo de ponteiro para void * é permitido, porque void * é definido como um tipo de ponteiro que possui um intervalo suficiente para representar qualquer valor que qualquer outro tipo de ponteiro possa. (Tecnicamente, apenas outro objeto Tipos de ponteiro, que exclui ponteiros às funções).

Isso não significa que void * tem o mesmo tamanho ou representação de qualquer outro tipo de ponteiro: converter um ponteiro de outro tipo de ponteiro em um void * não necessariamente deixa a representação subjacente inalterada. Convertendo de double * para void * é como converter de double para int - Isso tem que acontecer na visão completa do compilador, você não pode ocultar essa conversão nas costas do compilador.

Então isso implica que enquanto void * é um ponteiro genérico, void ** é não um ponteiro a ponteiro genérico. É um ponteiro para void * - uma void ** O ponteiro só deve apontar para real void * objetos (enquanto void * por si só pode apontar para qualquer coisa).

É por isso que não há conversões implícitas entre type ** e void ** - É pela mesma razão que não há conversões implícitas entre double * e int *.

Agora, há um caso especial: por razões históricas, char * é garantido que tenha o mesmo tamanho, representação e requisitos de alinhamento como void *. Isso significa que as conversões entre char ** (em particular) e void ** estão realmente OK, como uma exceção à regra geral. Então, em seu especial Caso, seu código está correto se você adicionar um elenco a void ** Quando você passa strarr para qsort1().

No entanto, você qsort1() é definido apenas para trabalhar corretamente em matrizes de void * ou char * (Incluindo unsigned char * etc.). Você não pode usá -lo para classificar uma matriz de double * Ponteiros, por exemplo (embora realmente funcionem nos ambientes mais comuns hoje).

Outras dicas

Qualquer ponteiro pode ser implicitamente convertido em um ponteiro vazio. Mas seu primeiro parâmetro não é Um ponteiro vazio - é uma variedade de ponteiros vazios, e não há conversão implícita para isso. Você provavelmente deseja declarar sua função como:

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

Mas é difícil dizer sem ver o código.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top