I was working on consolidating a code base (moving a qsort compar function to a new header /library so that it could be shared without being copy/pasta) and noticed something strange in the process.
Here is a demonstrative listing:
#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]);
}
Compile and run:
$ gcc -Wall main.c
$ ./a.out
AH AAAAA AH
ZING BOP POW
FRRING CRASH FOO
BO DELTA FO
FIDDLY ECHO ZOOOM
It's surprising to me that:
- The compiler has no warnings since the signature of the
comparfunction passed to quick sort does not have the prescribed function signatureint (*compar)(const void *, const void *). Even ingdb, when I runptype record_compare_field_1, it looks like the signature does not containconst *void. - The output is somehow correct? (Sorted based on field one (zero-indexed) results in
AAAAA, BOP, CRASH, DELTA, ECHO.
The questions are:
- Why/how does this work? Is this an old-school way of doing this?
- If I wanted to change the
qsortcomparfunction in use to use the proper signature, how would I do that (I been struggling trying to come up with the proper casts)?
Thank you!