struct reportItem *itemCopy = (struct reportItem *) malloc(sizeof(struct reportItem));
// ^^^^^^^^^^^^^^^^^^^^^
Приведение является ненужным и может скрыть ошибку, которую компилятор мог бы обнаружить при его отсутствии (1)
struct reportItem *itemCopy = malloc(sizeof(struct reportItem));
// ^^^^^^^^^^^^^^^^^^^
Использование самого типа здесь может рассматриваться как "авария, ожидающая случиться""(2).Безопаснее использовать сам объект
struct reportItem *itemCopy = malloc(sizeof *itemCopy);
Так что теперь это хорошо выглядящий оператор:)
Это вызывает библиотечную функцию malloc()
(которая пытается зарезервировать область памяти дляиспользуемую программу) и присваивает результирующее значение itemCopy
.
Ответственность программиста - проверить, удалось ли malloc()
зарезервировать память до , используя эту память.
if (itemCopy == NULL) {
//malloc failed to reserve memory
fprintf(stderr, "no memory.\n");
exit(EXIT_FAILURE);
}
Кроме того, программист отвечает за освобождение памяти (обратно в ОС), когда эта память больше не требуется.
//use itemCopy
free(itemCopy);
(1) ошибка скрытия приведения
Если в области действия malloc()
нет прототипа, компилятор предполагает, что он возвращает int
.Затем с помощью приведения молча преобразует этот недопустимый int
(недопустимый, потому что это, по сути, значение void*
) в указатель. Ошибка в отсутствии #include <stdio.h>
и приведении .Если вы просто удалите приведение, компилятор пожалуется на преобразование из int
в указатель.Если вы #include <stdio.h>
и сохраняете приведение, он является избыточным (а избыточный - плохим).
(2) использование типа для определения количества выделяемой памяти - это «ожидающая авария»
Вызов malloc(sizeof(struct whatever))
- это «случайность, которая должна произойти», потому что он заставляет программиста изменять код более чем в одном месте с одним изменением структуры.
Давайте представим, что есть struct Car
с некоторыми свойствами... Позже было решено изменить часть кода на новый обновленный struct Vehicle
(при этом struct Car
оставался активным).Использование имени типа в вызове malloc()
вызывает 2 изменения
struct Vehicle *x = malloc(sizeof (struct Vehicle));
// ^^^^^^^^^^^^^^^^ prevented accident
, тогда как для использования объекта требуется всего одно изменение
struct Vehicle *x = malloc(sizeof *x);
// ^^ *x is of the correct type