Использование qsort () внутри структуры с массивом структур не обеспечивает доступ к нужным элементам, кроме 0

У меня есть следующие 2 структуры:

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

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

и я хотел бы отсортировать Ancestor элементов массива по yearOfBirth. Вот как я вызываю qsort ():

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

а вот моя compare процедура:

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);
  }
}

Теперь мои выходные данные для a1 и a2 равны 0. Что я делаю не так?


person topkek    schedule 23.12.2018    source источник


Ответы (1)


Элементы в массиве относятся к типу Ancestor *, и это то, что вы должны использовать в качестве операнда для sizeof. Указатели, данные функции сравнения, являются указателями на тип элемента, приведенный к void *, следовательно, вы возвращаете их к Ancestor ** и разыменовываете.

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

или форма, которая всегда дает правильный размер, если сам массив правильно набран:

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

i.e.

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

И наконец

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);
}

И возвращаемое значение должно быть

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

чтобы избежать неопределенного поведения при экстремальных значениях int.

person Antti Haapala    schedule 23.12.2018
comment
a1->yearOfBirth - a2->yearOfBirth может переполниться и дать неправильный ответ и является UB. return (a1->yearOfBirth > a2->yearOfBirth) - (a1->yearOfBirth < a2->yearOfBirth); прекрасно справляется с этим. Конечно экстремальных лет не ожидается, такие значения могут встречаться как дозорные. - person chux - Reinstate Monica; 24.12.2018