Ответ 1
Ваше собственное объяснение является правильным. Pre-ANSI C ('K & R' C) не имел типа void *
с неявным преобразованием. char *
удвоен как тип псевдо void *
, но вам понадобилось явное преобразование типа.
В современном C литье нахмуривается, поскольку оно может подавлять предупреждения компилятора для отсутствующего прототипа malloc
. В С++ требуется кастинг (но там вы должны использовать new
вместо malloc
большую часть времени).
Update
Мои комментарии ниже, которые пытаются объяснить, почему требуется бросок, были немного неясны, я попытаюсь объяснить это лучше здесь. Вы можете подумать, что даже когда malloc
возвращает char *
, приведение не требуется, поскольку оно похоже на:
int *a;
char *b = a;
Но в этом примере также нужен актерский состав. Вторая строка является нарушением ограничения для простого оператора присваивания (C99 6.5.1.6.1). Оба операнда указателя должны быть совместимого типа. Когда вы измените это на:
int *a;
char *b = (char *) a;
нарушение ограничения исчезает (оба операнда теперь имеют тип char *
), и результат корректно определен (для преобразования в указатель char). В "обратной ситуации":
char *c;
int *d = (int *) c;
тот же аргумент выполняется для приведения, но когда int *
имеет более строгие требования к выравниванию, чем char *
, результат определяется реализацией.
Заключение: в дни до ANSI тип cast был необходим, потому что malloc
вернулся char *
, а не результаты кастинга - это ограничение ограничения для оператора '='.