Erro na função qsort na programação Pearls?
-
21-08-2019 - |
Pergunta
é só eu ou esse código em Programação Pérolas está errado (quicksort quer 2 vazios const, não?) Se assim for, é a minha solução certa? Desculpas, apenas aprender ...
int wordncmp(char *p, char* q)
{ int n = k;
for ( ; *p == *q; p++, q++)
if (*p == 0 && --n == 0)
return 0;
return *p - *q;
}
int sortcmp(char **p, char **q)
{ return wordncmp(*p, *q);
}
...
qsort(word, nword, sizeof(word[0]), sortcmp);
Isto é uma solução?
int sortcmp(const void *p, const void *q)
{ return wordncmp(* (char * const *) p, * (char * const *) q);
}
Solução
O primeiro exemplo de código irá provavelmente trabalhar com praticamente qualquer compilador e CPU; no entanto, é o comportamento tecnicamente indefinido, se você seguir o padrão C para a carta.
Como você disse, o último argumento para qsort()
é um ponteiro para uma função que toma dois argumentos do tipo const void*
. sortcmp
leva argumentos diferentes. Seu compilador deve dar-lhe um aviso sobre assinaturas de tipo incompatíveis ou algo assim. Em qualquer caso, um molde está a ser realizada a partir de uma função de um tipo de uma função de um outro tipo.
Os especifica C padrão que você pode lançar ponteiros de função para outros ponteiros de função com diferentes tipos, mas você não pode excluir a referência e invocar o ponteiro de função fundido. No entanto, se você re-converter o ponteiro de volta função para seu tipo original, em seguida, chamar esse comportamento definiu -. Ele chama a função original
Desde que você está fundição de um int (*)(char**, char**)
a um int (*)(const void*, const void*)
e, eventualmente, qsort()
está invocando a sua função de comparação sem convertê-lo de volta para int (*)(char**, char**)
, isso é um comportamento indefinido.
No entanto, uma vez que praticamente em todas as arquiteturas, um char **
e uma const void*
são representados da mesma forma, a chamada de função será praticamente sempre trabalho.
Se você deseja obter um comportamento definido, você tem que se certificar de sua função de comparação tem a assinatura de tipo apropriado, e, em seguida, você pode lançar os argumentos para o tipo adequado. Sua solução é exatamente correto e não viola o padrão C lá. Bem feito em const
-correção -. Um monte de pessoas não entendem exatamente o que significa char * const *
Você também deve fazer parâmetros wordncmp()
à recolha de const char*
, desde que você não está modificando os parâmetros.
Nota lateral: Também é tecnicamente não pode converter um ponteiro função de um ponteiro de dados (por exemplo, um void*
) ou vice-versa. A norma permite ponteiros de função e ponteiros de dados para ter tamanhos diferentes. Mesmo se ele funciona no seu computador, não é garantida para sempre trabalho.
Outras dicas
Você está correto, a assinatura para sortcmp
não corresponde ao que espera qsort
. Sua correção é certo. wordcmp
também deve ser feita const
-correto como você está tecnicamente perder algum do const
-ness ao longo do caminho.
int wordncmp(const char *p, const char* q)