Search code examples
cstructqsort

Using qsort() inside of struct with array of structs does not access the right elements but 0


I have the following 2 structs:

typedef struct {
  char fullName[40];
  int yearOfBirth;
} Ancestor;

typedef struct {
  Ancestor **ancestor;
  int capacity;
  int size;
} AncestorList;

and I would like to sort the Ancestor elements os the array by yearOfBirth. Here is how I call qsort():

qsort(listOfGreatUncles->ancestor, listOfGreatUncles->size, sizeof(Ancestor), compare); //listOfGreatUncles is a AncestorList struct

and here is my compare procedure:

int compare(const void *s1, const void *s2) {
  Ancestor *a1 = (Ancestor *)s1;
  Ancestor *a2 = (Ancestor *)s2;

  printf("a1 yearOfBirth %d\n", a1->yearOfBirth);
  printf("a2 yearOfBirth %d\n", a2->yearOfBirth);

  return (a1->yearOfBirth - a2->yearOfBirth);
  }
}

Now my output for a1 and a2 are 0. What am I doing wrong?


Solution

  • The elements in the array are of type Ancestor * and that's what you should use as the operand to sizeof. The pointers given to the comparison function are pointers to the element type cast to void *, hence you cast them back to Ancestor ** and dereference.

    qsort(listOfGreatUncles->ancestor, listOfGreatUncles->size, sizeof (Ancestor *), compare);
    

    or the form that always gives the right size if the array itself is properly typed:

    qsort(listOfGreatUncles->ancestor, 
          listOfGreatUncles->size, 
          sizeof listOfGreatUncles->ancestor[0],
          compare);
    

    i.e.

    qsort(array, length, sizeof array[0], compfunc);
    

    And finally

    int compare(const void *s1, const void *s2) {
        Ancestor *a1 = *(Ancestor **)s1;
        Ancestor *a2 = *(Ancestor **)s2;
    
        printf("a1 yearOfBirth %d\n", a1->yearOfBirth);
        printf("a2 yearOfBirth %d\n", a2->yearOfBirth);
    
        return (a1->yearOfBirth - a2->yearOfBirth);
    }
    

    And the return value should actually be

    return (a1->yearOfBirth > a2->yearOfBirth) - (a1->yearOfBirth < a2->yearOfBirth);
    

    to avoid undefined behaviour on extreme values of int.