Вопрос по c – Указатель приведен для использования с qsort

4

Этот фрагмент кода вручную скопирован из книги, которую я читаю:

/* scmp: string compare of *p1 and *p2 */
int scmp(const void *p1, const void *p2)
{
        char *v1, *v2;
        v1 = *(char **) p1; 
        v2 = *(char **) p2; 

        return strcmp(v1, v2);
}

Эта функция используется с qsort для сортировки массива строк. Дело в том, что я не понимаю, почемуv1 = *(char **) p1; вместо простоv1 = (char *) p1; или не будет даже этой работы;v1 = p1;? Я предполагаю, что компилятор должен автоматически ввести это назначение. Или даже, подумайте об этом:

/* scmp: string compare of *p1 and *p2 */
int scmp(const void *p1, const void *p2)
{
        return strcmp(p1, p2);
}

Я думаю (я могу быть ужасно не прав), компилятор должен типизироватьp1 а такжеp2 вchar * так как это то, чтоstrcmp(char *, char *) надеется.

Подводя итог, вопрос, почемуv1 = *(char **) p1 ?

Ваш Ответ

1   ответ
7

qsort передает в функцию сравнения указатель на элементы, которые он должен сравнивать; поскольку в C нет шаблонов, этот указатель просто жестоко приведен кconst void * (void * в C просто означает «это какой-то указатель», и для того, чтобы что-то с ним сделать, необходимо привести его обратно к его фактическому типу).

Теперь, если вы сортируете массив строк, каждый элемент, который вы должны сравнитьchar *; ноqsort переходит к функции сравненияpointer к каждому элементу, так что вашscmp получает на самом делеchar ** (указатель на указатель на первый символ строки), приведенный кconst void * потому что подпись функции сравнения говорит так.

Итак, чтобы получитьchar *сначала нужно преобразовать параметры в их фактический тип (char **), а затем разыменуйте этот указатель, чтобы получить фактическийchar * Вы хотите сравнить.

(хотя было бы правильнее с точки зрения константностиconst char **)

Похожие вопросы