Problema comstackndo el ejemplo de K&R

Tengo problemas para comstackr el progtwig de ejemplo presentado en la sección 5.11 del libro. He eliminado la mayor parte del código y solo he dejado las cosas relevantes.

#define MAXLINES 5000 char *lineptr[MAXLINES]; void qsort1(void *lineptr[], int left, int right, int (*comp)(void *, void *)); int numcmp(char *, char *); main(int argc, char *argv[]) { int numeric = 1; /* ... */ qsort1((void**) lineptr, 0, 100, (int (*)(void*, void*))(numeric ? numcmp : strcmp)); } void qsort1(void *v[], int left, int right, int (*comp)(void *, void *)) { /* ... */ } int numcmp(char *s1, char *s2) { /* ... */ } 

El problema es que el código no se comstack (estoy usando el comstackdor Digital Mars). El error que recibo es este:

  qsort1((void**) lineptr, 0, nlines - 1, (int (*)(void*, void*))(numeric ? numcmp : strcmp)); ^ go.c(19) : Error: need explicit cast to convert from: int (*C func)(char const *,char const *) to : int (*C func)(char *,char *) --- errorlevel 1 

Debe haber algo mal con las declaraciones, aunque pegué el código del libro correctamente. No sé lo suficiente como para realizar los cambios correctos (la sección sobre los punteros de función podría haberse escrito más extensamente).

EDITAR: Debería haber mencionado que estoy leyendo la versión ANSI del libro.

Creo que el error viene del hecho de que la antigua C no conocía todavía const: strcmp tomó dos punteros a caracteres no const ( char * ), creo (lo que podría ser la razón por la que se compiló en ese entonces, pero no con su comstackdor ). Sin embargo, hoy en día, strcmp toma char const* ( const char* es lo mismo). Cambia tu prototipo de función a esto:

 int numcmp(char const*, char const*); 

Ese es un problema común 🙂

La siguiente línea le dice a qsort que espere un puntero a una función con dos parámetros void *. Desafortunadamente, strcmp toma dos cadenas no modificables, por lo que su firma es

 int (*comp)(const char*, const char*) 

en lugar de lo que tienes

 int (*comp)(void *, void *) 

Cambia la firma de qsort1 y numeric :

 qsort1(void *v[], int left, int right, int (*comp)(const void *, const void *)) 

y:

 int numcmp(const char*, const char*) 

El puntero de función estándar esperado por qsort() o bsearch() tiene el prototipo:

 int comparator(const void *v1, const void *v2); 

El qsort1() definido en el código espera:

 int comparator(void *v1, void *v2); 

Las funciones de comparación definidas en el código no tienen ese prototipo, y no hay conversión automática entre diferentes tipos de punteros de función.

Entonces, las correcciones para qsort1() son:

  1. Introduzca un reparto: (int (*)(void *, void *)) , o
  2. Reescribe los comparadores:

     int numcmp(void *v1, void *v2) { char *s1 = v1; char *s2 = v2; ... } int str_cmp(void *v1, void *v2) // Note new function name! { return(strcmp(v1, v2)); } 

Obviamente, la llamada a qsort1() haría referencia a str_cmp lugar de a strcmp . Los autores trataron de evitar una función intermedia, pero se están quedando sin los comstackdores más exigentes (legítimamente) en uso hoy en día.

La versión estándar de qsort() requeriría un montón de calificadores const , como en la primera versión de esta respuesta.

Tenga en cuenta que strcmp toma dos argumentos const , mientras que su numcmp no lo hace. Por lo tanto, los tipos de las dos funciones no coinciden, y el ? : ? : operador se quejará.

Hacer uno de

  1. cambie numcmp para que coincida con el prototipo strcmp en términos de constness
  2. presione el (int (*)(void*, void*)) emitido dentro de ? : ? : por ejemplo

     numeric ? (int (*)(void*, void*))numcmp : (int (*)(void*, void*))strcmp 

Ha pasado un tiempo desde que hice cualquier progtwigción en C pura, no estoy seguro del nuevo estándar.

Sin embargo, la conversión al vacío ** crea un puntero a un puntero donde la función requiere un puntero a una matriz. Claro, son lo mismo internamente, pero una fuerte comprobación de tipos lo detectará como un error.

reescriba el qsort para aceptar ** en lugar de * [] y debería estar bien.