Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

153
Vistas
¿Por qué se puede llamar a `qsort` con una función de comparación con la firma incorrecta y la compilación no tiene advertencias?

Estaba trabajando en la consolidación de una base de código (mover una función de compar qsort a un nuevo encabezado/biblioteca para que pudiera compartirse sin ser copia/pasta) y noté algo extraño en el proceso.

Aquí hay una lista demostrativa:

 #include <stdlib.h> #include <string.h> #include <stdio.h> /** One record has three fields. * Each field contains a NULL terminated string of length at most 7 characters. */ typedef char Record[3][8]; int main(void) { Record database[5] = {0}; strcpy(database[0][0], "ZING"); strcpy(database[0][1], "BOP"); strcpy(database[0][2], "POW"); strcpy(database[1][0], "FIDDLY"); strcpy(database[1][1], "ECHO"); strcpy(database[1][2], "ZOOOM"); strcpy(database[2][0], "AH"); strcpy(database[2][1], "AAAAA"); strcpy(database[2][2], "AH"); strcpy(database[3][0], "BO"); strcpy(database[3][1], "DELTA"); strcpy(database[3][2], "FO"); strcpy(database[4][0], "FRRING"); strcpy(database[4][1], "CRASH"); strcpy(database[4][2], "FOO"); //(gdb) ptype record_compare_field_1 //type = int (char (*)[8], char (*)[8]) int record_compare_field_1(); qsort(database, 5, sizeof(Record), record_compare_field_1); for (int i = 0; i < 5; i++){ printf("%s\t%s\t%s\n", database[i][0], database[i][1], database[i][2]); } } /* Compares Records at field one. */ int record_compare_field_1(Record rowA, Record rowB) { return strcmp(rowA[1], rowB[1]); }

Compilar y ejecutar:

 $ gcc -Wall main.c $ ./a.out AH AAAAA AH ZING BOP POW FRRING CRASH FOO BO DELTA FO FIDDLY ECHO ZOOOM

Me sorprende que:

  • El compilador no tiene advertencias ya que la firma de la función de compar pasada a ordenación rápida no tiene la firma de función prescrita int (*compar)(const void *, const void *) . Incluso en gdb , cuando ejecuto ptype record_compare_field_1 , parece que la firma no contiene const *void .
  • ¿La salida es de alguna manera correcta? (Ordenados en función de los resultados del campo uno (índice cero) en AAAAA, BOP, CRASH, DELTA, ECHO .

Las preguntas son:

  • ¿Por qué/cómo funciona esto? ¿Es esta una forma de la vieja escuela de hacer esto?
  • Si quisiera cambiar la función de compar qsort en uso para usar la firma adecuada, ¿cómo lo haría (estuve luchando tratando de encontrar los moldes adecuados)?

¡Gracias!

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

El int record_compare_field_1(); declaración no tiene un prototipo. Esta es una característica obsoleta del estándar C17/C18.

En la función llamar a qsort(database, 5, sizeof(Record), record_compare_field_1); , el argumento record_compare_field_1 tiene tipo int (*)() y el parámetro compar de qsort tiene tipo int (*)(const void *, const void *) . Esto está permitido por esta regla de C17 6.2.7:

— Si solo un tipo es un tipo de función con una lista de tipos de parámetros (un prototipo de función), el tipo compuesto es un prototipo de función con la lista de tipos de parámetros.

La definición real de la función record_compare_field_1 tiene el prototipo int record_compare_field_1(Record, Record) donde el tipo de Record está definido por typedef char Record[3][8] . Dado que los parámetros de matriz se ajustan a punteros, esto es lo mismo que el prototipo int record_compare_field_1(char (*)[8], char (*)[8]) .

qsort llamará a la función pasada en record_compare_field_1 con el prototipo incorrecto, lo que generará un comportamiento indefinido . La mayoría de las implementaciones de C usan la misma representación para todos los tipos de punteros de objetos, por lo que le permite salirse con la suya.

Para hacerlo correctamente, la función record_compare_field_1 podría definirse así:

 int record_compare_field_1(const void *a, const void *b) { const Record *p_rowA = a; const Record *p_rowB = b; return strcmp((*p_rowA)[1], (*p_rowB)[1]); }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda