Search code examples
arrayscinitializationqsort

C: qsort() on struct array -- garbage is returned


I'd like to sort a struct array with the qsort() library function. I've read man 3 qsort thoroughly, and consulted other sources on the internet, however, with no luck.

I thought I had made sure that the nmemb and size arguments are correct.

I've also ensured that the issue didn't arise from my surrounding code, and rather comes from my lack of understanding of qsort(), by writing the following example:

#include <stdio.h>
#include <stdlib.h>

typedef struct example_structure {
    size_t a;
    size_t b;
} example_structure;

static int cmp_example_structure(const void *h1, const void *h2) {
    return (((example_structure *)h1)->a - ((example_structure *)h2)->a);
}

int main() {
    example_structure *example_structures = calloc(10, sizeof(example_structure));

    printf("sizeof(example_structures[0]) = %lu; sizeof(example_structure *) = %lu\n", sizeof(example_structures[0]), sizeof(example_structure *));

    fputc('\n', stdout);

    for(size_t h = 0; h < 10; h++) {
        example_structures[h].a = h;
        example_structures[h].b = h;
    }

    for(size_t h = 0; h < 10; h++) {
        printf("%ld ", example_structures[h].b);
    }

    fputc('\n', stdout);

    for(size_t h = 0; h < 10; h++) {
        printf("0x%lX ", example_structures[h].b);
    }

    fputc('\n', stdout);
    fputc('\n', stdout);

    qsort(example_structures, sizeof(example_structures[0]), 10, cmp_example_structure);

    for(size_t h = 0; h < 10; h++) {
        printf("%ld ", example_structures[h].b);
    }

    fputc('\n', stdout);

    for(size_t h = 0; h < 10; h++) {
        printf("0x%lX ", example_structures[h].b);
    }

    fputc('\n', stdout);

    free(example_structures);
}

I've noticed that the returned garbage appears to be shifted:

0 1 2 3 4 5 6 7 8 9 
0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 

0 1 17179869184 6 34359738368 131072 1970346311811072 131072 1970324836974592 9 
0x0 0x1 0x400000000 0x6 0x800000000 0x20000 0x7000500000000 0x20000 0x7000000000000 0x9 

How may I resolve this issue?

Thanks in advance.


Solution

  • qsort(3): sort array - Linux man page says:

    void qsort(void *base, size_t nmemb, size_t size,
               int (*compar)(const void *, const void *));
    

    The qsort() function sorts an array with nmemb elements of size size. The base argument points to the start of the array.

    As you see, you should specify the number of elements as the 2nd argument and the size of one element as the 3rd argument.

    In other words,

    qsort(example_structures, sizeof(example_structures[0]), 10, cmp_example_structure);
    

    should be

    qsort(example_structures, 10, sizeof(example_structures[0]), cmp_example_structure);