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