Кастинг пустых указателей - PullRequest
17 голосов
/ 24 августа 2010

Я видел много следующего в старом коде C:

type_t *x = (type_t *) malloc(...);

Какой смысл приводить указатель, возвращенный из malloc(), поскольку он void *? Это потому, что старые компиляторы C не поддерживали пустые указатели и вместо них malloc() возвращали char *?

Ответы [ 4 ]

23 голосов
/ 24 августа 2010

Ваше собственное объяснение правильное. До версии 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 *, а отсутствие результатов приведено как нарушение ограничения для оператора '='.

6 голосов
/ 24 августа 2010

Проблема здесь не в совместимости с любым диалектом C. Проблема C ++ .В C ++ указатель void нельзя автоматически преобразовать в любой другой тип указателя.Таким образом, без явного преобразования этот код не будет компилироваться с помощью компилятора C ++.

3 голосов
/ 24 августа 2010

Я не знаю, что malloc когда-либо возвращал символ *.

Но неявное приведение из void * к type_t * (или любому другому типу) не всегда было разрешено.Отсюда необходимость явного приведения к нужному типу.

0 голосов
/ 24 августа 2010

Какой смысл приводить указатель, возвращаемый функцией malloc (), так как он void *?

Совсем наоборот. Вам нужно , чтобы привести пустой указатель к фактическому типу, прежде чем вы сможете его использовать, поскольку void * ничего не означает о данных, хранящихся в этом месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...