Вы должны сделать это с локальными переменными, а не с глобальными, но общая идея будет такой же. Вы также должны стремиться к наличию массивов, а не кучи не связанных между собой переменных:
struct node {
int id;
struct node* next;
};
int main(){
struct node nodes[4];
for (int i = 0; i < 4; ++i) {
nodes[i].id = (3 - i);
if (i != 0) {
nodes[i].next = &nodes[i-1];
}
}
return 0;
}
Где что-то подобное собирает их в обратном порядке для удобства, но изначально все они сгруппированы в терминах памяти.
malloc
используется потому, что вы часто не знаете, сколько у вас будет, или они добавляются и удаляются непредсказуемо. Решение общего назначения выделит их по мере необходимости. Специализированная реализация может выделять их как один блок, но это очень ситуативно.
Здесь срок службы nodes
находится только внутри этой функции, поэтому, как только эта функция завершается, данные исчезают. Другими словами:
struct node* allocateNodes() {
struct node nodes[10];
return &nodes; // Returns a pointer to an out-of-scope variable, undefined behaviour
}
Это не сработает. Вам нужно более длительное распределение, которое именно то, что malloc
предоставляет:
struct node* allocateNodes() {
struct node *nodes = calloc(10, sizeof(struct node));
return nodes; // Returns a pointer to an allocated structure, which is fine
}
Проблема в том, что если вы malloc
ответственны за вызов free
, чтобы освободить память, значит, она становится более трудной.
Вы увидите оба стиля, используемые в коде, в зависимости от требуемой продолжительности жизни рассматриваемых переменных.