Первое: почему вы компилируете код C как C ++? . Пожалуйста, скомпилируйте его с помощью компилятора C.
Прототип list_sort()
:
void list_sort(INTLIST* list);
и list_map()
имеет прототип:
void list_map(INTLIST* list, void (*f)(void *));
Это означает, что второй аргумент list_map()
- это функция, которая принимает аргумент void *
и возвращает void
(ничего).
Теперь стандарт C гарантирует, что преобразование любого указателя объекта в void *
и обратно в порядке, поэтому дано:
INTLIST *l;
/* make l point to a valid INTLIST */
void *pl = l;
все в порядке:
list_sort(pl);
Обратите внимание, что list_sort()
мог быть объявлен как:
void list_sort_generic(void *l);
На самом деле, поскольку ваш профессор использует void *
в некоторых местах, он хочет расширить ваши списки, чтобы они в какой-то момент были универсального типа.
В любом случае, вы можете передать INTLIST *
в list_sort()
или list_sort_generic()
, но list_sort_generic()
можно передать любой указатель объекта, тогда как list_sort()
можно передать только INTLIST *
(или void *
, который был преобразован из INTLIST *
).
Даже если list_sort()
может принимать void *
, подпись list_sort()
не является
void list_sort(void *l);
Итак, типы функций list_sort()
и list_sort_generic()
не совпадают и не могут быть взаимозаменяемы. list_map()
ожидает функцию того же типа, что и list_sort_generic()
, но получает функцию другого типа.
Поскольку вы не можете менять прототипы, вам нужен состав. Теперь void *
является универсальным типом в C, так что вы могли бы подумать, что такое приведение будет работать. Но, как я уже говорил, только указатели объектов могут быть преобразованы в void *
и обратно - & mdash; не тип указателя на функцию. Таким образом, вам нужно привести list_sort()
к правильному типу при вызове list_map()
.
Это правильный тип void (*)(void *)
. Эта функция возвращает void
и принимает void *
.
Следовательно, вызов должен быть:
list_map(aList[i], (void (*)(void *))list_sort);
Но, поскольку тип list_sort()
и тип, ожидаемый list_map()
для его второго параметра, не совпадают, приведение может работать или не работать. Ваш профессор дал вам «не очень хорошие» (то есть неправильные ) прототипы. Либо он должен был пройти весь путь в объявлении типовых функций, либо он должен был оставить все INTLIST *
. Пройдя половину пути, он ввел сложный актерский состав, которого не должно было быть, и он может не работать. Я уверен, что если вы доведете это до сведения вашего профессора, он допустит этот недосмотр.
Надеюсь, это помогло.