Я специализируюсь на Coursera, и на уроке он объясняет функцию qsort (), которая сортирует заданный массив:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
где мы должны предоставить qsort () с четырьмя параметрами - массив для сортировки, количество элементов в массиве, размер каждого элемента массива и указатель на функцию (сравнение), которая принимает два const void * s и возвращает int. В уроке говорится, что нам нужно написать функцию compar
, чтобы она была совместима с функцией qsort
, поэтому, если мы хотим сравнить две строки, функция должна выглядеть так:
int compareStrings(const void * s1vp, const void * s2vp) {
// first const: s1vp actually points at (const char *)
// second const: cannot change *s1vp (is a const void *)
const char * const * s1ptr = s1vp;
const char * const * s2ptr = s2vp;
return strcmp(*s1ptr, *s2ptr);
}
void sortStringArray(const char ** array, size_t nelements) {
qsort(array, nelements, sizeof(const char *), compareStrings);
}
Она говорит: Обратите внимание, что переданные указатели являются указателями на элементы в массиве (то есть, они указывают на поля в массиве), хотя сами эти элементы являются указателями (поскольку они являются строками). Когда мы конвертируем их из void * s, , мы должны позаботиться о том, чтобы преобразовать их в правильный тип - здесь const char * const * - и используйте их должным образом, иначе наша функция каким-либо образом будет нарушена. Например, рассмотрим следующий неработающий код:
// BROKEN DO NOT DO THIS!
int compareStrings(const void * s1vp, const void * s2vp) {
const char * s1 = s1vp;
const char * s2 = s2vp;
return strcmp(s1, s2);
}
Я не могу понять, почему мы не рассмотрели s1vp и s2vp как указатели на указатели? Я имею в виду, поскольку аргументы, переданные в функцию compareStrings
, являются адресами указателей, указывающих на строки (адрес указателя), не должны ли мы объявить s1vp и s2vp как int compareStrings(const void ** s1vp, const void ** s2vp)
, поскольку они получают адреса указателей?
Другими словами, я передаю, например, адрес первого элемента массива строк, который на самом деле является указателем, на s1vp. Итак, теперь s1vp получает адрес указателя, а не переменную, поэтому мы должны объявить его как указатель на указатель, верно? Это дает мне предупреждение, когда я пытаюсь это сделать ...