struct Node* head = NULL;
head = (struct Node*) malloc(1 * sizeof(struct Node));
Эта форма излишне инициализирует head
в NULL
(нулевой указатель), а затем немедленно переназначает head
на результат вызова malloc()
.Это не является прямым вредом - и большинство компиляторов могут избежать этой начальной инициализации.Однако, это не очень хорошая привычка.
Явное преобразование типов (также называемое приведением) не требуется в C. Это также приведет к неопределенному поведению, если нет предшествующего #include <stdlib.h>
, поскольку - без <stdlib.h>
- компилятор примет, что malloc()
вернет int
.
Если предшествующего #include <stdlib.h>
нет, то без преобразования типов присвоение вызовет ошибку компиляции, поскольку int
не может быть неявно преобразован в указатель.Преобразование типов позволяет скомпилировать код путем принудительного преобразования из int
в указатель.В результате malloc()
возвращает указатель void
, это значение преобразуется в int
, а int
преобразуется обратно в указатель.Проблема в том, что указатели не гарантированно выживают в этом цикле конверсий, поэтому head
может не указывать на что-либо действительное.Поэтому любое последующее использование этого указателя (например, для доступа к членам узла) даст неопределенное поведение.
Таким образом, две вещи улучшат этот пример:
- непосредственно инициализируют
head
,вместо того, чтобы инициализировать его как NULL
, а затем сразу переназначить. - исключить преобразование типа
Конечный результат будет
struct Node* head = malloc(1 * sizeof(struct Node));
или, чтобы избежатьпроблемы, связанные с набором struct Node
дважды (например, замена одного, но не другого в будущем)
struct Node* head = malloc(1 * sizeof(*head));
Правильность вышеприведенного в вашей программе в целом зависит от того, какой другой кодработает с head
.
Во втором случае
struct Node* head = (struct Node*) malloc(1 * sizeof(struct Node));
head = NULL;
первая строка имеет тот же чистый эффект, что и первый пример, и предложенные мной корректировкик этому образцу применимы.
Второе утверждение (head = NULL
) немедленно отбрасывает значение, возвращаемое malloc()
.Ваша программа теперь не имеет возможности использовать эту память, а также не может освободить ее (поскольку значение, сохраненное malloc()
, не сохраняется ни в одной переменной).Однако эта память, выделенная malloc()
, останется выделенной, даже если ваша программа больше не сможет получить к ней доступ.В стандартном C нет средств, которые бы вызывали магическое освобождение во время работы вашей программы.
Если вы выполняете этот код много раз (например, он находится в функции, которая вызывается повторно), тогда происходит утечкабудет повторяться каждый раз, и ни одно из выделений никогда не будет освобождено во время работы вашей программы.Если это делается достаточно часто, это может привести к тому, что ваша программа исчерпает доступную память, что препятствует правильному выполнению.