2009-03-20 17 views
7

Duplicar posibles:
Problem compiling K&R examplepuntero advertencia de coincidencia de tipos en el ejemplo de K & R C

Últimamente he estado trabajando mi camino a través del lenguaje de programación C por K & R.

En la sección 5.11 cubren los punteros a las funciones y luego de escribir en su ejemplo: una implementación de quicksort donde proporcionamos un puntero al compás función hijo que queremos usar - Recibo una advertencia del compilador: el tipo de puntero no coincide en la expresión condicional. (Mi compilador gcc 4.0.1 es en OS X 10.5.6)

La línea del ejemplo que desencadena la alerta es:

qsort((void **) lineptr, 0, nlines-1, 
     (int (*)(void*, void*))(numeric ? numcmp : strcmp)); 

El programa se ejecuta sin violación de segmento, pero me gusta smoosh todas las advertencias Puedo, o al menos comprender sus causas.

La declaración de la función de numcmp parece:

int numcmp(char *, char *); 

Pero de acuerdo con la página de manual, stcmp tiene esta firma:

int strcmp(const char *s1, const char *s2); 

es la advertencia sencilla debido a las diferentes firmas de métodos poco? ¿Cuáles son las consecuencias de ignorar la advertencia?

+0

Eddie señaló una tontería. Voté para cerrar mi propia pregunta, pero pensé que habría una forma en que el propietario podría cerrarla sumariamente. – Dana

+0

Dana, consulte [Ejemplo de compilación del ejemplo de K & R] (http://stackoverflow.com/questions/616906/problem-compiling-kr-example/616929) y probablemente encontrará la respuesta a su pregunta allí. Háganos saber si no lo hace. – Eddie

Respuesta

1

Una forma de intentar diagnosticarlo es ver qué sucede si reemplaza la expresión con?: Con solo uno de los dos.

Si solo ocurre para strcmp y no para numcmp, podría ser debido a la const char *. Creo que aunque char * siempre se puede convertir a void *, no se puede convertir const char * en void * como "de forma segura".

Si es con ambos, entonces quizás se trate de un problema con los punteros a funciones, donde tener el char * convertido a void * funciona, pero las firmas deben ser idénticas y tener huecos en lugar de caracteres es un problema.

3

Respuesta corta: K & R no sabía C.

Respuesta larga: Ellos fueron obstaculizados por el hecho de que cuando empezaron, nadie sabía C, por lo que fueron una especie de inventando sobre la ellos fueron.

(ligeramente) forma menos impertinente de la respuesta larga: El lenguaje ha evolucionado (algunos dirían cambió) un poco desde K & R fue escrito, pero a menos que tengas la versión de libro electrónico con el ejemplo dinámico morphing, los ejemplos en su copia de K & R no se han mantenido con el lenguaje "nuevo y aprobado" ("¡ahora con aún más ANSI!").

7

Aunque puede convertir implícitamente un char * a un vacío *, no puede hacer lo mismo para un puntero de función con esos tipos (sin una advertencia). El compilador es más cuidadoso con la coincidencia de tipos en las firmas de funciones.

Sin mencionar que lo que está sucediendo dentro de qsort sería lo contrario: es decir, un vacío * se convertiría en un char * en numcmp y const char * en strcmp.

Y el compilador debería emitir una advertencia en estos casos. Si realmente tiene que usar una función que no tiene los mismos tipos que los parámetros, quizás deba usar una función de envoltura que coincida con los tipos, y luego haga el reparto explícito apropiado cuando llame a la función original.

Por ejemplo:

static int strcmp_wrapper(void* s1, void* s2) { 
    return strcmp((char*)s1, (char*)s2); 
} 

static int numcmp_wrapper(void* n1, void* n2) { 
    return numcmp((char*)n1, (char*)n2); 
} 

qsort((void **) lineptr, 0, nlines-1, 
     (numeric ? numcmp_wrapper : strcmp_wrapper)); 

y la firma moderna para qsort es

void 
qsort(void *base, size_t nel, size_t width, 
     int (*compar)(const void *, const void *)); 

No parece que la cuestión de la const a entrar en juego en su pregunta, pero K & R no lo hizo tener const.

+0

Otra opción es cambiar la expresión ternaria a lo siguiente: numeric? (int (*) (void *, void *)) numcmp: (int (*) (void *, void *)) strcmp); Simplemente pasando las dos funciones diferentes por separado a qsort. Esto también evitará las advertencias dadas por el compilador – bryanph

Cuestiones relacionadas