Нужно ли мне вызывать malloc() для другого поля в структуре после вызова malloc для самой этой структуры?

#c

#c

Вопрос:

Допустим, у меня есть тип node_t

 typedef struct node{
    char* value;
    struct node *next;
}node_t;
  

Когда я хочу создать новый указатель node_t с именем n1, я вызываю malloc

 node_t *n1 = malloc(sizeof(node_t));
  

Теперь я хочу получить доступ и использовать другие поля внутри n1 : value и далее, должен ли я снова вызывать malloc для этих указателей, вот так:

 n1->value = malloc(sizeof(char));
n1->next = malloc(sizeof(node_t));
  

Или самый первый вызов malloc() при создании n1 уже сделал все это?

Комментарии:

1. malloc выделяет новое node_t , и ничего больше. Он не инициализирует элементы выделенного struct и, конечно же, не выделяет память для любых указателей, которые являются членами struct .

2. sizeof(char) всегда равно 1 [по определению]. Итак, не используйте это. Итак, как правило, вы хотели бы (например) char str[] = "A string to store"; n1->value = strdup(str); И, опять же, при воссоздании данного узла (например) n1 вы не создаете next узел одновременно. Это происходит позже [обычно, при последующем вызове функции create]

Ответ №1:

должен ли я снова вызывать malloc для этих указателей

Это зависит от того, как вы хотите использовать эти элементы.

Когда вы выполняете malloc a, node_t вы получаете память для хранения 1) char указателя и 2) node_t указателя. Вы можете установить эти указатели так, чтобы они указывали на другие существующие объекты. Но вы также можете установить эти указатели так, чтобы они указывали на новые (динамически распределяемые) объекты.

Пример 1

 node_t *n1 = malloc(sizeof *n1);
assert(n1 != NULL);
n1->value = "Hello world";
n1->next = NULL;

node_t *n2 = malloc(sizeof *n2);
assert(n2 != NULL);
n2->value = "Have fun";
n2->next = NULL;

n1->next = n2;  // Create a linked list
  

В этом примере нет прямого malloc для каких-либо членов node_t . Члены просто настроены так, чтобы указывать на другие объекты.

Пример 2

 node_t *n1 = malloc(sizeof *n1);
assert(n1 != NULL);
n1->value = "Hello world";

n1->next = malloc(sizeof *n1->next);
assert(n1->next != NULL);
n1->next->value = "Have fun";
n1->next->next = NULL;
  

Этот пример приводит к тому же, что и первый пример. Это просто написано немного по-другому, т.Е. next указатель n1 присваивается для указания на новый malloc node_t вместо того, чтобы иметь n2 объект.

Пример 3

 char *str1= "Hello world";
char *str2= "Have fun";

node_t *n1 = malloc(sizeof *n1);
assert(n1 != NULL);
n1->value = malloc(1   strlen(str1));
strcpy(n1->value, str1);  // Copy the string

n1->next = malloc(sizeof *n1->next);
assert(n1->next != NULL);
n1->next->value = malloc(1   strlen(str2));
strcpy(n1->next->value, str2);  // Copy the string
n1->next->next = NULL;
  

Здесь value указатель устанавливается так, чтобы указывать на новый объект malloc, и в этот объект помещается копия строки.

Итак, повторяю — хотите ли вы использовать память malloc для членов, зависит от того, как вы хотите использовать структуру.

Комментарии:

1. Не используйте assert для проверки возвращаемого значения malloc . assert предназначен для проверки ошибок программирования во время отладки, а не для ошибок во время выполнения. Для c-реализации совершенно нормально определять assert как не-операцию.